在本文中,我們學習瞭如何使用Lombok的@Locked註解。
Lombok 引入了該註釋以更好地支援虛擬執行緒。它代表了ReentrantLock物件的替代。我們看到如何使用@Lock.Read和@Lock.Write註釋來指定讀寫鎖,而不是使用通用鎖。最後,我們重點介紹了 @Locked和@Synchronized註釋之間的幾個區別。
Project Lombok是一個 Java 庫,它提供了各種註釋,我們可以使用它們來生成標準方法和功能,從而減少樣板程式碼。例如,我們可以使用 Lombok 生成 getter 和 setter、建構函式,甚至在程式碼中引入設計模式,例如Builder 模式。
在本教程中,我們將學習如何使用Lombok 版本 1.18.32 中引入的@Locked註釋。
為什麼要使用@Locked註解?
首先,讓我們瞭解@Locked註釋的必要性。
Java 21引入了虛擬執行緒,以簡化併發應用程式的實現、維護和除錯。它們與標準執行緒的區別在於,它們由 JVM 而不是作業系統管理。因此,它們的分配不需要系統呼叫,也不依賴於作業系統的上下文切換。
但是,我們應該意識到虛擬執行緒可能帶來的潛在效能問題。例如,當阻塞操作在同步塊或方法內執行時,它仍然會阻塞作業系統的執行緒。這種情況稱為鎖定。另一方面,如果阻塞操作在同步塊或方法之外,則不會引起任何問題。
此外,固定可能會對應用程式的效能產生負面影響,尤其是當阻塞操作被頻繁呼叫且持續時間較長時。值得注意的是,不頻繁且持續時間較短的阻塞操作不會引起此類問題。
解決固定問題的一種方法是用ReentrantLock替換synchronized。這就是新的 Lombok 註釋發揮作用的地方。
理解@Locked註解
簡單來說,@Locked註解是作為ReentrantLock的一個變體而建立的,其主要目的是為虛擬執行緒提供更好的支援。
此外,我們只能在靜態或例項方法上使用此註解。它將方法中提供的整個程式碼包裝到獲取鎖的塊中。此外,我們可以指定要用於鎖定的ReentrantLock型別的欄位。結果,Lombok 對該特定欄位執行鎖定。方法執行完成後,它將解鎖。
現在,讓我們看看@Locked註釋的實際作用。
依賴設定
讓我們在pom.xml中新增lombok依賴項:
<dependency> |
值得注意的是,我們需要 1.18.32 或更高版本才能使用此註釋。
使用
讓我們使用increment()和get()方法建立Counter類:
public class Counter { |
由於counter++不是原子操作,因此我們需要包含鎖定,以確保共享物件的原子更新在多執行緒環境中對其他執行緒可見。否則,我們將得到不正確的結果。
這裡,我們使用ReentrantLock來鎖定increment()和get()方法,確保一次只有一個執行緒可以呼叫該方法。
讓我們替換increment()和get()方法中的鎖 ,並改用@Locked註釋:
@Locked |
我們將程式碼行數減少到每個方法只有一行。現在,讓我們瞭解一下底層發生了什麼。Lombok 建立一個名為$LOCK或$lock的ReentrantLock型別的新欄位,具體取決於我們是在靜態方法還是例項方法上使用鎖定。
然後,它將方法中提供的程式碼包裝到獲取ReentrantLock的塊中。最後,當我們退出該方法時,它會釋放鎖。
此外,使用@Locked註釋註釋的多個方法將共享同一個鎖。如果我們需要不同的鎖,我們可以建立一個ReentrantLock例項變數並將其名稱作為引數傳遞給@Locked註釋。
讓我們測試這些方法以確保它們正常工作:
@Test |
@Locked.Read和@Locked.Write註釋
我們可以使用@Locked.Read和@Locked.Write註釋代替ReentrantReadWriteLock。
顧名思義,用@Locked.Read lock註釋的方法對讀鎖起作用,而用@Locked.Write lock註釋的方法對寫鎖起作用。
讓我們修改increment()和get()方法中提供的程式碼 並使用@Locked.Write和@Locked.Read註釋:
@Locked.Write |
提醒一下,對讀寫操作使用單獨的鎖可以提高效能,特別是在操作繁重時。
值得注意的是, Lombok 建立的ReentrantReadWriteLock欄位的名稱 與為@Locked註釋生成的欄位名稱相同。因此,如果我們想在同一個類中使用這兩個註釋,我們需要為其中一個鎖指定一個自定義名稱。
@Locked和@Synchronized之間的區別
除了@Locked註解外,Lombok還提供了類似的@Synchronized註解,這兩個註解的目的都是保證執行緒安全,下面我們來看一下它們的區別。
@Locked註釋是ReentrantLock的替代品,而@Synchonized註釋則取代了synchronized修飾符。就像關鍵字一樣,我們只能在靜態或例項方法上使用它。但是,synchronized鎖定this ,而註釋鎖定 Lombok 建立的特定欄位。
此外,使用虛擬執行緒時建議使用@Locked註解,而在相同情況下使用@Synchronized可能會導致效能問題。