Java鎖對象和條件對象的使用


鎖對象

臨界區:臨界區是一個特殊的代碼段,該代碼段訪問某種特殊的公共資源,該資源同一時間只允許一個線程使用。

Java中可以使用鎖對象創造一個臨界區:

1 myLock.lock();
2 try {
3     關鍵代碼
4 } finally {
5     myLock.unlock();
6 }

 

使用這種結構可以確保關鍵代碼不會同時被多個線程執行,線程想要執行關鍵代碼必須先獲取“鎖”,“鎖”只能被一個線程持有,在該線程將“鎖”釋放前,其他線程因為獲取不到鎖而被阻塞,“鎖”被釋放的時候,之前因為獲取這個鎖被掛起的線程都會被喚醒,共同競爭着去獲取鎖。

將釋放鎖的操作寫在finally里是很重要的,防止某個線程執行關鍵代碼的時候因為拋出異常而沒有將鎖釋放。

 

 

 1 package learnspringboot.xiao.learnjava.thread;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 import java.util.concurrent.locks.Condition;
 6 import java.util.concurrent.locks.Lock;
 7 import java.util.concurrent.locks.ReentrantLock;
 8 
 9 /**
10  * @author xzy
11  * @date 2019-12-13 11:01
12  * 說明:模擬銀行轉賬
13  */
14 public class Bank {
15     private Map<String, Double> accountMap = new HashMap<>();
16     private Lock myLock = new ReentrantLock();
17     private Condition haveMoney = myLock.newCondition();
18 
19     public Bank() {
20         this.accountMap.put("ZhangSan", 100.0);
21         this.accountMap.put("WangWu", 1000.0);
22     }
23 
24     public void transfer(String from, String to, Double money) {
25         //線程執行后面的代碼段需要先獲得鎖,獲取不到就掛起。
26         myLock.lock();
27         System.out.println("當前獲得鎖的線程:" + Thread.currentThread().getName());
28         System.out.println(from + "想給" + to + "轉" + money + "元," + from + "現在有" + accountMap.get(from) + "元");
29         try {
30             while (accountMap.get(from) < money) {
31                 System.out.println("線程阻塞:" + Thread.currentThread().getName());
32                 //獲取到鎖的線程需要等待本條件成立,條件成立前將鎖釋放,線程阻塞。
33                 haveMoney.await();
34             }
35             accountMap.put(from, accountMap.get(from) - money);
36             accountMap.put(to, accountMap.get(to) + money);
37             System.out.println(from + "轉給" + to + money + "元  線程:" + Thread.currentThread().getName());
38             //通知因本條件而掛起的線程,條件現在可能已經滿足,可以試着再去獲取肯看。
39             haveMoney.signalAll();
40         } catch (Exception e) {
41             e.printStackTrace();
42         } finally {
43             myLock.unlock();
44         }
45     }
46 
47     public static void main(String[] args) {
48         Bank bank = new Bank();
49         Thread thread1 = new Thread(() -> {
50             bank.transfer("ZhangSan", "WangWu", 500.0);
51         });
52         Thread thread2 = new Thread(() -> {
53             bank.transfer("WangWu", "ZhangSan", 1000.0);
54         });
55         Thread thread3 = new Thread(() -> {
56             bank.transfer("ZhangSan", "WangWu", 500.0);
57         });
58         thread1.setName("張三給王五500 x1");
59         thread2.setName("王五給張三1000");
60         thread3.setName("張三給王五500 x2");
61         thread1.start();
62         thread2.start();
63         thread3.start();
64         while (true) {
65 
66         }
67     }
68 }
View Code

 


免責聲明!

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



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