多執行緒(四)鎖
阿新 • • 發佈:2022-02-20
多執行緒(四)鎖
目錄死鎖
- 一個同步塊同時擁有“兩個以上物件的鎖”時,就可能會發生“死鎖”的問題(相互等待對方的資源)
產生死鎖的條件
- 以下死鎖的四個必要條件,只要想辦法破其中的任意一個或者多個條件就可以避免死鎖的發生
- 互斥條件:一個資源每次只能被一個程序使用
- 請求與保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放
- 不剝奪條件:程序已獲得的資源,在未使用完之前,不能強制剝奪
- 迴圈等待條件:若干程序之間形成一種頭尾相接的迴圈等待資源關係
Lock鎖
- 通過顯示定義同步鎖物件來實現同步。同步鎖使用Lock物件充當
- ReentrantLock類實現了Lock
Lock鎖和synchronized鎖的區別
-
- Lock是顯示鎖(手動)
- synchronized是隱式鎖
-
- Lock只有程式碼塊鎖
- synchronized有程式碼塊鎖和方法鎖
-
- Lock效能更好
程式碼例項
死鎖
- 張三要鏡子,但是鏡子在李四手上,李四要口紅,但是口紅在張三手上
- 死鎖,永遠不會停止
public class SXP10 { public static void main(String[] args) { Makeup g1=new Makeup(0,"張三"); Makeup g2=new Makeup(1,"李四"); g1.start(); g2.start(); } } //口紅 class Lipstick{ } //鏡子 class Mirror{ } class Makeup extends Thread{ //需要的資源只有一份,用static來保證只有一份 static Lipstick lipstick=new Lipstick(); static Mirror mirror=new Mirror(); int choice; String girlNmae;//使用化妝品的人 Makeup(int choice,String girlNmae){ this.choice=choice; this.girlNmae=girlNmae; } @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.girlNmae+"獲得口紅的鎖"); Thread.sleep(1000); synchronized (mirror){//1秒鐘之後獲得鏡子的鎖 System.out.println(this.girlNmae+"獲得鏡子的鎖"); } } }else{ synchronized (mirror) {//獲得鏡子的鎖 System.out.println(this.girlNmae + "獲得鏡子的鎖"); Thread.sleep(2000); synchronized (lipstick){//1秒鐘之後獲得口紅的鎖 System.out.println(this.girlNmae+"獲得口紅的鎖"); } } } } }
防止上述死鎖
public class SXP10 { public static void main(String[] args) { Makeup g1=new Makeup(0,"張三"); Makeup g2=new Makeup(1,"李四"); g1.start(); g2.start(); } } //口紅 class Lipstick{ } //鏡子 class Mirror{ } class Makeup extends Thread{ //需要的資源只有一份,用static來保證只有一份 static Lipstick lipstick=new Lipstick(); static Mirror mirror=new Mirror(); int choice; String girlNmae;//使用化妝品的人 Makeup(int choice,String girlNmae){ this.choice=choice; this.girlNmae=girlNmae; } @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.girlNmae+"獲得口紅的鎖"); Thread.sleep(1000); } synchronized (mirror){//1秒鐘之後獲得鏡子的鎖 System.out.println(this.girlNmae+"獲得鏡子的鎖"); } }else{ synchronized (mirror) {//獲得鏡子的鎖 System.out.println(this.girlNmae + "獲得鏡子的鎖"); } Thread.sleep(2000); synchronized (lipstick){//1秒鐘之後獲得口紅的鎖 System.out.println(this.girlNmae+"獲得口紅的鎖"); } } } } //輸出: 張三獲得口紅的鎖 李四獲得鏡子的鎖 張三獲得鏡子的鎖 李四獲得口紅的鎖
Lock鎖
public class Sxp11 {
public static void main(String[] args) {
TestLock2 t1=new TestLock2();
new Thread(t1).start();
new Thread(t1).start();
new Thread(t1).start();
}
}
class TestLock2 implements Runnable{
int ticketNums=10;
//定義lock鎖
private final ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
while (true){
try {
lock.lock();//加鎖
if(ticketNums>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(ticketNums--);
}else {
break;
}
}finally {
//解鎖
lock.unlock();
}
}
}
}
//輸出:
10
9
8
7
6
5
4
3
2
1