Java 中的鎖(Locking)機制主要是為了解決多線程環(huán)境下,對共享資源并發(fā)訪問時的同步和互斥控制,以確保共享資源的安全訪問。
鎖的作用主要體現(xiàn)在以下幾個方面:
在 Java 中有很多鎖策略,用于對鎖進行分類和指導鎖的(具體)實現(xiàn),這些鎖策略包括以下內(nèi)容:
在 Java 中也有一些具體的鎖實現(xiàn),用于代碼層面的鎖操作以此來保證線程安全的,這些常見的鎖實現(xiàn)有以下幾個:
synchronized 可以用來修飾普通方法、靜態(tài)方法和代碼塊。
public synchronized void method() { // .......}
當 synchronized 修飾普通方法時,被修飾的方法被稱為同步方法,其作用范圍是整個方法,作用的對象是調(diào)用這個方法的對象。
public static synchronized void staticMethod() { // .......}
當 synchronized 修飾靜態(tài)的方法時,其作用的范圍是整個方法,作用對象是調(diào)用這個類的所有對象。
為了減少鎖的粒度,我們可以選擇在一個方法中的某個部分使用 synchronized 來修飾(一段代碼塊),從而實現(xiàn)對一個方法中的部分代碼進行加鎖,實現(xiàn)代碼如下:
public void classMethod() throws InterruptedException { // 前置代碼... // 加鎖代碼 synchronized (SynchronizedExample.class) { // ...... } // 后置代碼...}
以上代碼在執(zhí)行時,被修飾的代碼塊稱為同步語句塊,其作用范圍是大括號“{}”括起來的代碼塊,作用的對象是調(diào)用這個代碼塊的對象。
ReentrantLock 基本使用:
// 1. 創(chuàng)建ReentrantLock對象ReentrantLock lock = new ReentrantLock();// 2.獲取鎖lock.lock(); try { // 3.得到鎖,執(zhí)行需要同步的代碼塊} finally { // 4.釋放鎖 lock.unlock(); }
進階使用:嘗試獲取鎖并設(shè)定超時時間(可選):
ReentrantLock lock = new ReentrantLock(); // 嘗試獲取鎖,等待2秒,超時返回falseboolean locked = lock.tryLock(2, TimeUnit.SECONDS);if (locked) { try { // 執(zhí)行需要同步的代碼塊 } finally { lock.unlock(); }}
ReentrantReadWriteLock 特點如下:
也就是說:讀讀不互斥、讀寫互斥、寫寫互斥。
ReentrantReadWriteLock 基礎(chǔ)使用如下:
// 創(chuàng)建 ReentrantReadWriteLock 對象ReentrantReadWriteLock lock = new ReentrantReadWriteLock();// 創(chuàng)建讀鎖ReentrantReadWriteLock.ReadLock readLock = lock.readLock();// 獲取讀鎖readLock.lock(); try { // 讀取共享資源的操作} finally { // 釋放讀鎖 readLock.unlock(); }// 創(chuàng)建寫鎖ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();// 獲取寫鎖writeLock.lock();try { // 寫入共享資源的操作} finally { // 釋放寫鎖 writeLock.unlock(); }
StampedLock 有三種讀寫方法:
其中 readLock() 和 writeLock() 方法與 ReentrantReadWriteLock 的用法類似,而 tryOptimisticRead() 方法則是 StampedLock 引入的新方法,它用于非常短的讀操作,它是使用如下:
// 創(chuàng)建 StampedLock 實例StampedLock lock = new StampedLock();// 獲取樂觀讀鎖long stamp = lock.tryOptimisticRead(); // 讀取共享變量if (!lock.validate(stamp)) { // 檢查樂觀讀鎖是否有效 stamp = lock.readLock(); // 如果樂觀讀鎖無效,則獲取悲觀讀鎖 try { // 重新讀取共享變量 } finally { lock.unlockRead(stamp); // 釋放悲觀讀鎖 }}// 獲取悲觀讀鎖long stamp = lock.readLock(); try { // 讀取共享變量} finally { lock.unlockRead(stamp); // 釋放悲觀讀鎖}// 獲取寫鎖long stamp = lock.writeLock(); try { // 寫入共享變量} finally { lock.unlockWrite(stamp); // 釋放寫鎖}
使用樂觀讀鎖的特性可以提高讀操作的并發(fā)性能,適用于讀多寫少的場景。如果樂觀讀鎖獲取后,在讀取共享變量前發(fā)生了寫入操作,則 validate 方法會返回 false,此時需要轉(zhuǎn)換為悲觀讀鎖或?qū)戞i重新訪問共享變量。
本文鏈接:http://www.tebozhan.com/showinfo-26-88356-0.html字節(jié)面試:說說Java中的鎖機制?
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com