日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java.util.concurrent.Locks使用指南

發布時間:2025/3/20 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java.util.concurrent.Locks使用指南 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.概述

簡而言之,鎖是一種比標準同步塊更靈活,更復雜的線程同步機制。

自Java 1.5以來,Lock接口一直存在。它在java.util.concurrent.lock包中定義,它提供了大量的鎖定操作。

在本文中,我們將探討Lock接口及其應用程序的不同實現。

2.?鎖定(Lock)和同步塊(Synchronized?)之間的差異

  • 同步塊被完全包含在方法中(創建和釋放鎖在同一個方法內);? ? ? ?Lock可以將lock()?和?unlock()放在不同的方法中
  • synchronized塊不支持公平性,一旦鎖釋放,任何線程可能獲得鎖;? ?  ? ?通過指定公平屬性,我們可以在Lock?API中實現公平。它確保最長的等待線程可以訪問鎖
  • 如果線程無法訪問同步塊,則會阻塞該線程;? ? ? ? ? ?Lock?API提供的tryLock()方法,只有當鎖可用且沒有任何其他線程持有時,線程才會獲取鎖定。這減少了線程等待鎖定的阻塞時間(可以設置嘗試獲取鎖的時間)
  • 處于“等待”狀態以獲取對同步塊的訪問的線程不能被中斷;? ? ? ? Lock??API提供了一種方法lockInterruptibly()??,其可以用來中斷等待鎖線程。

3. Lock?API

我們來看看Lock接口中的方法:

  • void lock()??-獲取鎖(如果可用);?如果鎖不可用,則線程會被阻塞,直到鎖被釋放
  • void lockInterruptibly()?- 這類似于?lock(),但它允許被阻塞的線程被中斷并通過拋出的java.lang.InterruptedException恢復執行
  • boolean tryLock()?- 這是?lock()方法的非阻塞版本;?它會立即嘗試獲取鎖定,如果鎖定成功則返回true
  • boolean tryLock(long timeout,TimeUnit timeUnit)?-這類似于?tryLock(),除了它在放棄嘗試獲取?Lock之前等待給定的超時
  • void?unlock()?- 解鎖Lock實例

執行完畢應始終釋放鎖以避免死鎖情況。使用鎖的推薦代碼塊應包含try / catch和finally塊:

Lock lock = ...; lock.lock(); try {// access to the shared resource } finally {lock.unlock(); }

除了??Lock接口之外,我們還有一個ReadWriteLock接口,它維護一對鎖,一個用于只讀操作,另一個用于寫操作。只要沒有寫入,讀鎖可以由多個線程同時保持。

ReadWriteLock聲明獲取讀或寫鎖的方法:

  • Lock readLock()?-返回用于讀取的鎖
  • Lock writeLock()?- 返回用于寫入的鎖

4.?鎖的實現

4.1.ReentrantLock(重入鎖)

ReentrantLock類實現Lock接口。它提供了相同的并發和內存語義.

public class SharedObject {//...ReentrantLock lock = new ReentrantLock();int counter = 0;public void perform() {lock.lock();try {// Critical section herecount++;} finally {lock.unlock();}}//... }

我們需要確保在try-finally塊中包裝lock()和unlock()調用以避免死鎖情況。

讓我們看看tryLock()如何使用:

public void performTryLock(){//...boolean isLockAcquired = lock.tryLock(1, TimeUnit.SECONDS);if(isLockAcquired) {try {//Critical section here} finally {lock.unlock();}}//... }

在這種情況下,調用tryLock()的線程將最多等待一秒鐘(如果直接拿到鎖則不用等待),并且如果鎖不可用則放棄等待。

4.2.ReentrantReadWriteLock

ReentrantReadWriteLock類實現ReadWriteLock接口。

讓我們看一下線程獲取ReadLock或WriteLock的規則:

  • 讀鎖?- 如果沒有線程獲得寫鎖或請求它,則多個線程可以獲取讀鎖
  • 寫鎖-? 如果沒有線程正在讀取或寫入,則只有一個線程可以獲取寫入鎖

讓我們看看如何使用ReadWriteLock:

public class SynchronizedHashMapWithReadWriteLock {Map<String,String> syncHashMap = new HashMap<>();ReadWriteLock lock = new ReentrantReadWriteLock();// ...Lock writeLock = lock.writeLock();public void put(String key, String value) {try {writeLock.lock();syncHashMap.put(key, value);} finally {writeLock.unlock();}}...public String remove(String key){try {writeLock.lock();return syncHashMap.remove(key);} finally {writeLock.unlock();}}//... }

?

Lock readLock = lock.readLock(); //... public String get(String key){try {readLock.lock();return syncHashMap.get(key);} finally {readLock.unlock();} }public boolean containsKey(String key) {try {readLock.lock();return syncHashMap.containsKey(key);} finally {readLock.unlock();} }

4.3.StampedLock

StampedLock在Java 8中引入。它還支持讀寫鎖定。但是,鎖獲取方法會返回一個用于釋放鎖或檢查鎖是否仍然有效的戳記:

public class StampedLockDemo {Map<String,String> map = new HashMap<>();private StampedLock lock = new StampedLock();public void put(String key, String value){long stamp = lock.writeLock();try {map.put(key, value);} finally {lock.unlockWrite(stamp);}}public String get(String key) throws InterruptedException {long stamp = lock.readLock();try {return map.get(key);} finally {lock.unlockRead(stamp);}} }

StampedLock提供的另一個功能是樂觀鎖定。大多數時候,讀操作不需要等待寫操作完成,因此不需要真正的讀鎖。

如果出現并發,我們可以升級到讀鎖:

public String readWithOptimisticLock(String key) {long stamp = lock.tryOptimisticRead();String value = map.get(key);if(!lock.validate(stamp)) {stamp = lock.readLock();try {return map.get(key);} finally {lock.unlock(stamp); }}return value; }

5.使用條件

該條件類提供了一個線程等待在執行關鍵部分出現一些狀況的能力。

當線程獲得對臨界區的訪問但沒有執行其操作的必要條件時,可能會發生這種情況。例如,讀者線程可以訪問共享隊列的鎖,該隊列仍然沒有任何數據要消耗。

傳統上,Java?為線程互通提供了wait(),notify()和notifyAll()方法。條件有類似的機制,但另外,我們可以指定多個條件:

public class ReentrantLockWithCondition {Stack<String> stack = new Stack<>();int CAPACITY = 5;ReentrantLock lock = new ReentrantLock();Condition stackEmptyCondition = lock.newCondition();Condition stackFullCondition = lock.newCondition();public void pushToStack(String item){try {lock.lock();while(stack.size() == CAPACITY) {stackFullCondition.await();}stack.push(item);stackEmptyCondition.signalAll();} finally {lock.unlock();}}public String popFromStack() {try {lock.lock();while(stack.size() == 0) {stackEmptyCondition.await();}return stack.pop();} finally {stackFullCondition.signalAll();lock.unlock();}} }

對比:

  Condition提供的方法和Java原生的wait(),notify(),notifyAll()功能類似,但是可以同時創建多個Condition條件,而java原生則不能指定特定的條件。

六,結論

在本文中,我們已經看到了Lock接口和新引入的StampedLock類的不同實現。我們還探討了如何使用Condition類來處理多個條件。

轉載于:https://www.cnblogs.com/gc65/p/10631176.html

總結

以上是生活随笔為你收集整理的java.util.concurrent.Locks使用指南的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。