java執行緒死鎖講解,白雪公主與灰姑娘搶口紅和鏡子的案例
阿新 • • 發佈:2020-12-07
技術標籤:需理解# 多執行緒java多執行緒thread併發程式設計
1.死鎖程式碼
//死鎖:多個執行緒互相抱著對方需要的資源,然後形成僵局
public class DeadLock {
public static void main(String[] args) {
Makeup girl1 = new Makeup(0,"灰姑娘");
Makeup girl2 = new Makeup(1,"白雪公主");
girl1.start();
girl2.start();
}
}
//口紅
class Lipstick{
}
//鏡子
class Mirror{
}
class Makeup extends Thread{
//需要的資源只能有一份,用static來保證只有一份
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choice;//選擇
String girlName;//使用化妝品的人
public Makeup(int choice, String girlName) {
this .choice = choice;
this.girlName = girlName;
}
@Override
public void run(){
try {
makeup();//化妝
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void makeup() throws InterruptedException {
if (choice == 0){
synchronized (lipstick){//獲得口紅的鎖
System.out.println(this.girlName+"獲得口紅的鎖");
Thread.sleep(1000);
synchronized (mirror){//一秒鐘後想獲得鏡子
System.out.println(this.girlName+"獲取鏡子的鎖");
}
}
}else {
synchronized (mirror){//獲得鏡子的鎖
System.out.println(this.girlName+"獲得鏡子的鎖");
Thread.sleep(2000);
synchronized (lipstick){//兩秒鐘後,想獲得口紅
System.out.println(this.girlName+"獲取口紅的鎖");
}
}
}
}
}
關鍵程式碼
private void makeup() throws InterruptedException {
if (choice == 0){
synchronized (lipstick){//獲得口紅的鎖
System.out.println(this.girlName+"獲得口紅的鎖");
Thread.sleep(1000);
synchronized (mirror){//一秒鐘後想獲得鏡子
System.out.println(this.girlName+"獲取鏡子的鎖");
}
}
}else {
synchronized (mirror){//獲得鏡子的鎖
System.out.println(this.girlName+"獲得鏡子的鎖");
Thread.sleep(2000);
synchronized (lipstick){//兩秒鐘後,想獲得口紅
System.out.println(this.girlName+"獲取口紅的鎖");
}
}
}
}
上述程式碼解析,當一個執行緒A鎖住口紅不放,同時想拿鏡子
但是鏡子被執行緒B鎖住,執行緒B要拿到了口紅才會釋放鏡子
那麼執行緒A就會一直等待執行緒B釋放鏡子鎖
但是執行緒B要拿不到口紅鎖就不會釋放鏡子鎖
所以兩個執行緒互相等待,形成死鎖,程式崩潰
執行結果
2.解決後的程式碼
private void makeup() throws InterruptedException {
if (choice == 0){
synchronized (lipstick){//獲得口紅的鎖
System.out.println(this.girlName+"獲得口紅的鎖");
Thread.sleep(1000);
}
synchronized (mirror){//一秒鐘後想獲得鏡子
System.out.println(this.girlName+"獲取鏡子的鎖");
}
}else {
synchronized (mirror){//獲得鏡子的鎖
System.out.println(this.girlName+"獲得鏡子的鎖");
Thread.sleep(2000);
}
synchronized (lipstick){//兩秒鐘後,想獲得口紅
System.out.println(this.girlName+"獲取口紅的鎖");
}
}
}
執行緒A拿到了口紅鎖,然後釋放了口紅鎖,想拿鏡子鎖
執行緒B拿到了鏡子鎖,然後釋放了鏡子鎖,再拿口紅鎖
雙方達成共識,不會永久的等待
執行結果