Java同步鎖(synchronized)、鎖(lock)以及死鎖


1、實體類

 1 package com.cn.donleo.thread.phone;
 2 
 3 import java.util.concurrent.locks.Lock;
 4 import java.util.concurrent.locks.ReentrantLock;
 5 
 6 /**
 7  * @author liangd
 8  * date 2020-11-02 08:53
 9  * code
10  */
11 public class MyPhone implements Runnable {
12 
13     private int phoneNum = 100;
14     /*
15      * 同步鎖的兩種方式:
16      * 1、鎖對象   synchronized (this)
17      * 2、鎖方法   public synchronized void run()   鎖方法其實是鎖的當前對象,synchronized (this) ,synchronized (MyPhone.class)
18      * 同步鎖優缺點:
19      * 1、解決了多線程安全問題
20      * 2、增加了線程同步鎖后,必須一個一個執行,浪費資源,降低了程序的運行效率
21      */
22     /**
23      * 1、對不同的runnable傳入同一個lock
24      * 2、lock和synchronized類似,只不過這個是手動上鎖,手動釋放鎖
25      *    synchronized屬於自動上鎖和釋放
26      * 3、Lock和synchronized的區別
27      *   1)synchronized試用於並發量小的,lock更適用於並發量大的
28      *   2)lock更靈活,可以自由定義多把鎖的枷鎖解鎖順序
29      *   3)Lock還有中斷鎖和定時鎖。
30      *   4)當線程運行到synchronized同步方法中,就會擁有obj對象的對象鎖
31      *   5)Wait會釋放對象鎖,sleep不會釋放對象鎖
32      *   6)Synchronized用對象鎖:
33      */
34     private Lock lock = new ReentrantLock();
35 
36     @Override
37     public synchronized void run() {
38         //while(true)是一個無窮循環語句  我們必須在他的循環語句內部加入一個判斷  當他達到了什么要求就會跳出
39         while (true) {
40             //鎖對象,指當前對象
41 //            synchronized (this){
42 //            synchronized ("Myphone"){
43             if (phoneNum > 0) {
44                 lock.lock();
45                 try {
46                     /*
47                         1、賣手機的時候不可能都是同時賣出或者被預定在MyPhone類里面增加sleep
48                          休眠100毫秒
49                         2、淘寶最后一部手機進來
50                            京東也有人預定手機,現在沒有--,也可以進來
51                            同理,拼多多也有人預定手機,現在沒有--,也可以進來
52                         3、會出現負數
53                      */
54                     Thread.sleep(100);
55                 } catch (InterruptedException e) {
56                     e.printStackTrace();
57                 } finally {
58                     //lock.unlock()要放在finally里面,因為如果上面報異常的情況下鎖就不會手動釋放,放在finally里面始終要執行
59                     lock.unlock();
60                 }
61                 System.out.println(Thread.currentThread().getName() + "賣出了一部手機,還剩余" + --phoneNum + "部手機");
62             } else {
63                 System.out.println("手機已經全部賣完,請下次再來");
64                 return;
65             }
66 //            }
67 
68         }
69     }
70 }

 

2、測試同步鎖

 1 package com.cn.donleo.thread.phone;
 2 
 3 /**
 4  * @author liangd
 5  * date 2020-11-02 08:59
 6  * code 線程同步測試
 7  */
 8 public class TestMyPhone {
 9     /**
10      * 手機屬於預定模式,分別由京東,淘寶,拼多多三個商家在賣
11      * 現在有華為P40PRO手機100部,怎么來實現
12      * 思考:
13      * 1.有一百部手機
14      * 2.京東,淘寶,拼多多是同時賣手機,屬於三個線程
15      * 3.有一個倉庫進行發貨,這個可以理解為main方法
16      * @param args
17      */
18     public static void main(String[] args){
19         MyPhone myPhone = new MyPhone();
20             Thread tb = new Thread(myPhone,"淘寶");
21             Thread jd = new Thread(myPhone,"京東");
22             Thread pdd = new Thread(myPhone,"拼多多");
23             tb.start();
24             jd.start();
25             pdd.start();
26 
27     }
28 }

 

3、測試死鎖

 1 package com.cn.donleo.thread.phone;
 2 
 3 /**
 4  * @author liangd
 5  * date 2020-11-02 09:42
 6  * code 死鎖測試
 7  */
 8 public class TestSynchronized {
 9     /**
10      * 1、死鎖4個必要條件
11      *  (1) 互斥條件:一個資源每次只能被一個進程使用。
12      *  (2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
13      *  (3) 不剝奪條件:進程已獲得的資源,在未使用完之前,不能強行剝奪。
14      *  (4) 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
15      * 2、如何避免死鎖
16      *  (1)加鎖順序(線程按照一定的順序加鎖)
17      *  (2)加鎖時限(線程嘗試獲取鎖的時候加上一定的時限,超過時限則放棄對該鎖的請求,並釋放自己占有的鎖)
18      *  (3)死鎖檢測
19      *   最簡單的方式:不要寫嵌套鎖就好
20      */
21     public static void main(String[] args) {
22         /*
23          *  多次測試,出現死鎖,程序一直在運行,A和B都沒有吃到飯
24          */
25         //匿名內部類,直接new接口必須實現接口中的抽象方法
26         new Thread(new Runnable() {
27             @Override
28             public void run() {
29                 synchronized ("A") {
30                     System.out.println(Thread.currentThread().getName() + "拿到A筷子了");
31                     //嵌套鎖
32                     synchronized ("B") {
33                         System.out.println(Thread.currentThread().getName() + "拿到A筷子了,同時拿到B筷子了,可以吃飯了");
34                     }
35                 }
36             }
37         }, "男朋友").start();
38         //再開一個線程
39         new Thread(new Runnable() {
40             @Override
41             public void run() {
42                 synchronized ("B") {
43                     System.out.println(Thread.currentThread().getName() + "拿到B筷子了");
44                     //嵌套鎖
45                     synchronized ("A") {
46                         System.out.println(Thread.currentThread().getName() + "拿到B筷子了,同時拿到A筷子了,可以吃飯了");
47                     }
48                 }
49             }
50         }, "女朋友").start();
51     }
52 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM