Java執行緒同步 執行緒死鎖
阿新 • • 發佈:2021-08-02
解決超賣
package ersatz.thread; public class T { public static void main(String[] args) { Ticket ticket = new Ticket(); new Thread(ticket).start(); new Thread(ticket).start(); new Thread(ticket).start(); } } class Ticket implements Runnable { private int number = 50; private boolean loop = true; Object o = new Object(); // 同步方法(static)的鎖為當前類 // public synchronized static void m(){} 鎖加在Ticket.class // 靜態方法中,實現一個同步程式碼塊 // synchronized (Ticket.class) { // // } public static void m() { synchronized (Ticket.class) { System.out.println(); } } // public synchronized void m(){}是一個同步方法,鎖在this,可在程式碼塊寫synchronized,同步程式碼塊,互斥鎖還是在this public /*synchronized*/ void sell() { // 同步方法,在同一時刻,只能有一個執行緒來執行sell方法 synchronized (/*this*/ o) { if (number <= 0) { System.out.println("ticket out of number"); loop = false; return; } try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " sell ticket " + "left: " + --number); } } @Override public void run() { while (loop) sell(); } }
以下程式碼不能解決超賣
package ersatz.thread; public class T { public static void main(String[] args) { Ticket ticket1 = new Ticket(); Ticket ticket2 = new Ticket(); Ticket ticket3 = new Ticket(); ticket1.start(); ticket2.start(); ticket3.start(); } } class Ticket extends Thread { private static int number = 50; private boolean loop = true; public void sell() { synchronized (this) { if (number <= 0) { System.out.println("ticket out of number"); loop = false; return; } try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " sell ticket: " + number + ", left: " + --number); } } @Override public void run() { while (loop) sell(); } }
Deadlock
package ersatz.thread;
public class T {
public static void main(String[] args) {
Deadlock d1 = new Deadlock(true);
Deadlock d2 = new Deadlock(false);
d1.setName("Thread-A");
d2.setName("Thread-B");
d1.start();
d2.start();
}
}
class Deadlock extends Thread {
protected static final Object o1 = new Object(); // 保證多執行緒共享同一物件
protected static final Object o2 = new Object();
protected boolean flag;
public Deadlock(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
//1. 如果flag 為 T, 執行緒A 就會先得到/持有 o1 物件鎖, 然後嘗試去獲取 o2 物件鎖
//2. 如果執行緒A 得不到 o2 物件鎖,就會Blocked
//3. 如果flag 為 F, 執行緒B 就會先得到/持有 o2 物件鎖, 然後嘗試去獲取 o1 物件鎖
//4. 如果執行緒B 得不到 o1 物件鎖,就會Blocked
if (flag) {
synchronized (o1) { // 物件互斥鎖,下面為同步程式碼
System.out.println(Thread.currentThread().getName() + " obtain o1 lock");
synchronized (o2) {
System.out.println(Thread.currentThread().getName() + " obtain o2 lock");
}
}
} else {
synchronized (o2) {
System.out.println(Thread.currentThread().getName() + " obtain o2 lock");
synchronized (o1) {
System.out.println(Thread.currentThread().getName() + " obtain o1 lock");
}
}
}
}
}
釋放鎖:
下列操作不會釋放鎖
package ersatz.thread;
import java.util.Scanner;
public class T {
public static void main(String[] args) {
A a = new A();
B b = new B(a);
a.setName("Thread-A");
b.setName("Thread-B");
a.start();
b.start();
}
}
class A extends Thread {
private boolean loop = true;
public void setLoop(boolean loop) {
this.loop = loop;
}
@Override
public void run() {
while (loop) {
System.out.println((int) (Math.random() * 100 + 1));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " exit");
}
}
class B extends Thread {
private A a = null;
private final Scanner scanner = new Scanner(System.in);
public B(A a) {
this.a = a;
}
@Override
public void run() {
while (true) {
System.out.println("input Q to exit:");
char key = scanner.next().toUpperCase().charAt(0);
if (key == 'Q') {
a.setLoop(false);
System.out.println(Thread.currentThread().getName() + " exit");
break;
}
}
}
}
package ersatz.thread;
public class T {
public static void main(String[] args) {
B b = new B();
Thread t1 = new Thread(b);
t1.setName("Thread-A");
Thread t2 = new Thread(b);
t2.setName("Thread-B");
t1.start();
t2.start();
}
}
class B implements Runnable{
private int balance=10000;
@Override
public void run() {
do {
synchronized (this) {
if (balance < 1000) {
System.out.println("insufficient balance: " + balance+' '+Thread.currentThread().getName()+" exit");
break;
}
System.out.println(Thread.currentThread().getName() + " withdraw 1000, balance: " + (balance -= 1000));
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (true);
}
}