首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java ReentrantReadWriteLock 讀寫鎖實戰:Runnable 任務封裝與多線程驗證示例

     編輯:程式設計疑難解答

核心概念

  • 讀鎖(共享鎖):多線程可同時持有,讀讀不互斥;
  • 寫鎖(排他鎖):同一時間僅一線程持有,讀寫、寫寫互斥;
  • 鎖降級:寫鎖 → 讀鎖 支持,讀鎖 → 寫鎖 不支持(需釋放讀鎖再獲取寫鎖)。

原始代碼 Bug 修正

// 原代碼 finally 中寫鎖調用了 w.lock(),應為 w.unlock()
finally { w.unlock(); }

完整驗證Demo

// 共享資源
class DataStore {
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    private final Lock r = rwl.readLock(), w = rwl.writeLock();
    private String data = "init";

    public void read() {
        r.lock();
        try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " read: " + data); }
        catch (InterruptedException e) { Thread.currentThread().interrupt(); }
        finally { r.unlock(); }
    }
    public void write(String v) {
        w.lock();
        try { Thread.sleep(3000); data = v; System.out.println(Thread.currentThread().getName() + " wrote: " + v); }
        catch (InterruptedException e) { Thread.currentThread().interrupt(); }
        finally { w.unlock(); }
    }
}

// 讀任務
class ReadTask implements Runnable {
    private final DataStore store;
    ReadTask(DataStore s) { store = s; }
    public void run() { store.read(); }
}

// 寫任務
class WriteTask implements Runnable {
    private final DataStore store; private final String val;
    WriteTask(DataStore s, String v) { store = s; val = v; }
    public void run() { store.write(val); }
}

// 主程序
public class RWLockDemo {
    public static void main(String[] args) {
        DataStore store = new DataStore();
        // 2 寫線程(互斥)、4 讀線程(並發)
        new Thread(new WriteTask(store, "v1"), "W-1").start();
        new Thread(new WriteTask(store, "v2"), "W-2").start();
        for (int i = 1; i <= 4; i++)
            new Thread(new ReadTask(store), "R-" + i).start();
    }
}

預期輸出現象

  • 兩寫線程**串行**(間隔 ~3s);
  • 四讀線程**幾乎同時**打印(讀鎖共享);
  • 寫期間讀線程阻塞,讀期間寫線程阻塞。

最佳實踐提醒

  • 業務讀多寫少場景優先考慮 ReentrantReadWriteLock;
  • 避免在鎖內調用耗時 IO / 睡眠,縮小臨界區;
  • Java 8+ 可考慮 StampedLock(樂觀讀、無條件遞歸),性能更優但 API 較複雜。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved