Java 中 Lock 接口詳解:靈活強大的線程同步機制

在 Java 中,Lock 是一個接口,它提供了比 synchronized 關鍵字更靈活、更強大的線程同步機制。以下將詳細介紹 Lock 接口及其實現類,以及它與 synchronized 相比的優點。

Lock 接口及其實現類介紹

Lock 接口

Lock 接口定義了一系列用于獲取和釋放鎖的方法,主要方法如下:

  • void lock():獲取鎖,如果鎖不可用,則當前線程將被阻塞,直到鎖被釋放。
  • void lockInterruptibly():可中斷地獲取鎖,在獲取鎖的過程中,如果當前線程被中斷,則會拋出 InterruptedException 異常。
  • boolean tryLock():嘗試非阻塞地獲取鎖,如果鎖可用,則獲取鎖并返回 true;否則返回 false。
  • boolean tryLock(long time, TimeUnit unit):在指定的時間內嘗試獲取鎖,如果在該時間內鎖可用,則獲取鎖并返回 true;否則返回 false。如果在等待過程中線程被中斷,則會拋出 InterruptedException 異常。
  • void unlock():釋放鎖。
  • Condition newCondition():返回一個與該鎖關聯的 Condition 對象,用于實現線程間的等待 - 通知機制。

常見實現類

  • ReentrantLock:可重入鎖,是 Lock 接口最常用的實現類。它支持與 synchronized 相同的可重入特性,即同一個線程可以多次獲取同一把鎖而不會被阻塞。
  • ReentrantReadWriteLock:讀寫鎖,它維護了一對鎖,一個讀鎖和一個寫鎖。多個線程可以同時獲取讀鎖,但寫鎖是排他的,即同一時間只能有一個線程獲取寫鎖,并且在寫鎖被持有時,其他線程不能獲取讀鎖或寫鎖。

Lock 與 synchronized 對比的優點

1. 靈活性更高
  • 鎖的獲取和釋放可分離:synchronized 是基于代碼塊或方法的,鎖的獲取和釋放是隱式的,由 JVM 自動完成。而 Lock 接口的 lock() 和 unlock() 方法可以在不同的代碼塊中調用,這使得鎖的獲取和釋放更加靈活。
    例如,在某些復雜的業務邏輯中,可能需要在不同的條件下釋放鎖,使用 Lock 可以很方便地實現這一點。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class LockFlexibilityExample {private final Lock lock = new ReentrantLock();public void complexOperation() {lock.lock();try {// 執行一些操作if (someCondition()) {return;}// 繼續執行其他操作} finally {lock.unlock();}}private boolean someCondition() {// 模擬條件判斷return Math.random() > 0.5;}
}

在上述代碼中,如果 someCondition() 方法返回 true,則會提前退出方法,但在 finally 塊中仍然可以確保鎖被釋放。

  • 可中斷的鎖獲取:Lock 接口提供了 lockInterruptibly() 方法,允許線程在獲取鎖的過程中被中斷。而 synchronized 關鍵字在獲取鎖時是不可中斷的,一旦線程進入阻塞狀態,就只能等待鎖被釋放。這在某些場景下非常有用,例如當線程需要響應中斷信號來執行其他操作時。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class InterruptibleLockExample {private final Lock lock = new ReentrantLock();public void interruptibleTask() throws InterruptedException {lock.lockInterruptibly();try {// 執行任務System.out.println("獲取到鎖,執行任務");} finally {lock.unlock();}}public static void main(String[] args) {InterruptibleLockExample example = new InterruptibleLockExample();Thread thread = new Thread(() -> {try {example.interruptibleTask();} catch (InterruptedException e) {System.out.println("線程被中斷");}});thread.start();// 中斷線程thread.interrupt();}
}

在上述代碼中,線程在獲取鎖的過程中被中斷,會拋出 InterruptedException 異常,從而可以進行相應的處理。

2. 可實現公平鎖

ReentrantLock 可以通過構造函數指定是否為公平鎖。公平鎖是指線程按照請求鎖的順序依次獲取鎖,避免了某些線程長時間得不到鎖的情況。而 synchronized 關鍵字是非公平鎖,線程獲取鎖的順序是不確定的,可能會導致某些線程饑餓。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class FairLockExample {private final Lock fairLock = new ReentrantLock(true);public void fairTask() {fairLock.lock();try {// 執行任務System.out.println(Thread.currentThread().getName() + " 獲取到公平鎖");} finally {fairLock.unlock();}}public static void main(String[] args) {FairLockExample example = new FairLockExample();for (int i = 0; i < 5; i++) {new Thread(example::fairTask, "Thread-" + i).start();}}
}

在上述代碼中,ReentrantLock 被初始化為公平鎖,線程會按照請求鎖的順序依次獲取鎖。

3. 支持多個條件變量

Lock 接口的 newCondition() 方法可以返回一個與該鎖關聯的 Condition 對象,一個 Lock 可以關聯多個 Condition 對象,從而實現更精細的線程間通信。而 synchronized 關鍵字只能使用 wait()、notify() 和 notifyAll() 方法,這些方法是基于對象的監視器,只能實現簡單的線程間等待 - 通知機制。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ConditionExample {private final Lock lock = new ReentrantLock();private final Condition notFull = lock.newCondition();private final Condition notEmpty = lock.newCondition();private final int[] buffer = new int[10];private int count = 0;private int in = 0;private int out = 0;public void put(int value) throws InterruptedException {lock.lock();try {while (count == buffer.length) {notFull.await();}buffer[in] = value;in = (in + 1) % buffer.length;count++;notEmpty.signal();} finally {lock.unlock();}}public int take() throws InterruptedException {lock.lock();try {while (count == 0) {notEmpty.await();}int value = buffer[out];out = (out + 1) % buffer.length;count--;notFull.signal();return value;} finally {lock.unlock();}}
}

在上述代碼中,notFull 和 notEmpty 是兩個不同的 Condition 對象,分別用于控制緩沖區滿和緩沖區空的情況,實現了更精細的線程間通信。
總結
Lock 接口及其實現類提供了比 synchronized 關鍵字更靈活、更強大的線程同步機制,在需要更精細的鎖控制、可中斷的鎖獲取、公平鎖和多個條件變量等場景下,Lock 是更好的選擇。但 synchronized 關鍵字使用起來更加簡單,在一些簡單的同步場景下仍然是首選。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/82069.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/82069.shtml
英文地址,請注明出處:http://en.pswp.cn/web/82069.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

實驗分享|基于sCMOS相機科學成像技術的耐高溫航空涂層材料損傷檢測實驗

1實驗背景 航空發動機外殼的耐高溫涂層材料在長期高溫、高壓工況下易產生微小損傷與裂紋&#xff0c;可能導致嚴重安全隱患。傳統光學檢測手段受限于分辨率與靈敏度&#xff0c;難以捕捉微米級缺陷&#xff0c;且檢測效率低下。 某高校航空材料實驗室&#xff0c;采用科學相機…

python訓練營day40

知識點回顧&#xff1a; 彩色和灰度圖片測試和訓練的規范寫法&#xff1a;封裝在函數中展平操作&#xff1a;除第一個維度batchsize外全部展平dropout操作&#xff1a;訓練階段隨機丟棄神經元&#xff0c;測試階段eval模式關閉dropout 作業&#xff1a;仔細學習下測試和訓練代碼…

Baklib企業CMS全流程管控與智能協作

企業CMS全流程管控方案解析 現代企業內容管理中&#xff0c;全流程管控的實現依賴于對生產、審核、發布及迭代環節的系統化整合。通過動態發布引擎與元數據智能標記技術&#xff0c;系統可自動匹配內容與目標場景&#xff0c;實現標準化模板驅動的快速部署。針對多分支機構的復…

Qt程序添加調試輸出窗口:CONFIG += console

目錄 1.背景 2.解決方案 3.原理詳解 4.控制臺窗口的行為 5.條件編譯&#xff08;僅調試模式顯示控制臺&#xff09; 6.替代方案 7.總結 1.背景 在Qt程序開發中&#xff0c;開發者經常遇到這樣的困擾&#xff1a; 開發機上程序運行正常 發布到其他機器后程序無法啟動 …

《江西棒球資訊》棒球運動發展·棒球1號位

聯賽體系結構 | League Structure MLB模式 MLB采用分層體系&#xff08;大聯盟、小聯盟&#xff09;&#xff0c;強調梯隊建設和長期發展。 MLB operates a tiered system (Major League, Minor League) with a focus on talent pipelines and long-term development. 中國現…

Python爬蟲實戰:研究Tornado框架相關技術

1. 引言 1.1 研究背景與意義 網絡爬蟲作為一種自動獲取互聯網信息的程序,在信息檢索、數據挖掘、輿情分析等領域有著廣泛的應用。隨著互聯網數據量的爆炸式增長,對爬蟲的性能和效率提出了更高的要求。傳統的同步爬蟲在處理大量 URL 時效率低下,而異步爬蟲可以顯著提高并發…

Vue-列表過濾排序

列表過濾 基礎環境 數據 persons: [{ id: "001", name: "劉德華", age: 19 },{ id: "002", name: "馬德華", age: 20 },{ id: "003", name: "李小龍", age: 21 },{ id: "004", name: "釋小龍&q…

JDK21深度解密 Day 9:響應式編程模型重構

【JDK21深度解密 Day 9】響應式編程模型重構 引言&#xff1a;從Reactor到虛擬線程的范式轉變 在JDK21中&#xff0c;虛擬線程的引入徹底改變了傳統的異步編程模型。作為"JDK21深度解密"系列的第91天&#xff0c;我們將聚焦于響應式編程模型重構這一關鍵主題。通過…

UE5打包項目設置Project Settings(打包widows exe安裝包)

UE5打包項目Project Settings Edit-Project Settings- Packaging-Ini Section Denylist-Advanced 1&#xff1a;打包 2&#xff1a;高級設置 3&#xff1a;勾選創建壓縮包 4&#xff1a;添加要打包地圖Map的數量 5&#xff1a;選擇要打包的地圖Maps 6&#xff1a;Project-Bui…

Fastapi 學習使用

Fastapi 學習使用 Fastapi 可以用來快速搭建 Web 應用來進行接口的搭建。 參考文章&#xff1a;https://blog.csdn.net/liudadaxuexi/article/details/141062582 參考文章&#xff1a;https://blog.csdn.net/jcgeneral/article/details/146505880 參考文章&#xff1a;http…

java helloWord java程序運行機制 用idea創建一個java項目 標識符 關鍵字 數據類型 字節

HelloWord public class Hello{public static void main(String[] args) {System.out.print("Hello,World!");} }java程序運行機制 用idea創建一個java項目 建立一個空項目 新建一個module 注釋 標識符 關鍵字 標識符注意點 數據類型 public class Demo02 {public st…

隨機響應噪聲-極大似然估計

一、核心原因&#xff1a;噪聲機制的數學可逆性 在隨機響應機制&#xff08;Randomized Response&#xff09;中使用極大似然估計&#xff08;Maximum Likelihood Estimation, MLE&#xff09;是為了從擾動后的噪聲數據中無偏地還原原始數據的統計特性。隨機響應通過已知概率的…

SMT貼片機工藝優化與效率提升策略

內容概要 現代電子制造領域中&#xff0c;SMT貼片機作為核心生產設備&#xff0c;其工藝優化與效率提升直接影響企業競爭力。本文聚焦設備參數校準、吸嘴選型匹配、SPI檢測技術三大技術模塊&#xff0c;結合生產流程重構與設備維護周期優化兩大管理維度&#xff0c;形成系統性…

AI提示工程(Prompt Engineering)高級技巧詳解

AI提示工程(Prompt Engineering)高級技巧詳解 文章目錄 一、基礎設計原則二、高級提示策略三、輸出控制技術四、工程化實踐五、專業框架應用提示工程是與大型語言模型(LLM)高效交互的關鍵技術,精心設計的提示可以顯著提升模型輸出的質量和相關性。以下是經過驗證的詳細提示工…

光電設計大賽智能車激光對抗方案分享:低成本高效備賽攻略

一、賽題核心難點與備賽痛點解析 全國大學生光電設計競賽的 “智能車激光對抗” 賽題&#xff0c;要求參賽隊伍設計具備激光對抗功能的智能小車&#xff0c;需實現光電避障、目標識別、軌跡規劃及激光精準打擊等核心功能。從歷年參賽情況看&#xff0c;選手普遍面臨三大挑戰&a…

【KWDB 創作者計劃】_再熱垃圾發電汽輪機仿真與監控系統:KaiwuDB 批量插入10萬條數據性能優化實踐

再熱垃圾發電汽輪機仿真與監控系統&#xff1a;KaiwuDB 批量插入10萬條數據性能優化實踐 我是一臺N25-3.82/390型汽輪機&#xff0c;心臟在5500轉/分的轟鳴中跳動。垃圾焚燒爐是我的胃&#xff0c;將人類遺棄的殘渣轉化為金色蒸汽&#xff0c;沿管道涌入我的胸腔。 清晨&#x…

day23-計算機網絡-1

1. 網絡簡介 1.1. 網絡介質 網線&#xff1a;cat5,cat5e 六類網線&#xff0c;七類網線&#xff0c;芭蕾網線光纖&#xff1a;wifi&#xff1a;無線路由器&#xff0c;ap5G 1.2. 常見網線類型 1.2.1. 雙絞線&#xff08;Twisted Pair Cable&#xff09;【最常用】 按性能主…

VR/AR 視網膜級顯示破局:10000PPI 如何終結顆粒感時代?

一、傳統液晶 “紗窗效應”&#xff1a;VR 沉浸體驗的最大絆腳石 當用戶首次戴上 VR 頭顯時&#xff0c;眼前密密麻麻的像素網格往往打破沉浸感 —— 這正是傳統液晶顯示在近眼場景下的致命缺陷。受限于 500-600PPI 的像素密度&#xff0c;即使達到 4K 分辨率&#xff0c;等效到…

2022---不重復版的數的劃分-且范圍太大

1.數的劃分--數的劃分--dfs剪枝-CSDN博客 2.范圍太大&#xff0c;這題用dp 3.狀態轉移公式其中1是泛指 #include<bits/stdc.h> using namespace std; #define N 100011 typedef long long ll; typedef pair<int,int> pii; ll dp[2025][12]; int n,k; void solv…

day15 leetcode-hot100-29(鏈表8)

19. 刪除鏈表的倒數第 N 個結點 - 力扣&#xff08;LeetCode&#xff09; 1.暴力法 思路 &#xff08;1&#xff09;先獲取鏈表的長度L &#xff08;2&#xff09;然后再次遍歷鏈表到L-n的位置&#xff0c;直接讓該指針的節點指向下下一個即可。 2.哈希表 思路 &#xff0…