首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 5 線程新特性:Lock 介面與 ReentrantLock 實戰(上)

     編輯:Java 相關知識

Lock 優於 synchronized 的特性

java.util.concurrent.locks.Lock 提供更靈活的鎖操作:

  • 可中斷獲取鎖:lockInterruptibly()
  • 非阻塞嘗試:tryLock()、tryLock(timeout)
  • 公平/非公平選擇:new ReentrantLock(true) 公平鎖
  • 條件變量:newCondition() 支持多等待隊列
  • 鎖狀態檢查:isLocked()、getHoldCount() 等

核心接口體系

  • Lock:基礎鎖接口,ReentrantLock 實現
  • Condition:將 wait/notify 解耦為對象,支持多條件隊列
  • ReadWriteLock:讀寫分離鎖,ReentrantReadWriteLock 實現

代碼示例:ReentrantLock 保護賬戶操作

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test {
    public static void main(String[] args) {
        MyCount myCount = new MyCount("95599200901215522", 10000);
        Lock lock = new ReentrantLock(); // 非公平鎖
        ExecutorService pool = Executors.newCachedThreadPool();
        
        pool.execute(new User("張三", myCount, -4000, lock));
        pool.execute(new User("張三他爹", myCount, 6000, lock));
        pool.execute(new User("張三他弟", myCount, -8000, lock));
        pool.execute(new User("張三", myCount, 800, lock));
        pool.shutdown();
    }
}

class User implements Runnable {
    private String name; private MyCount myCount; private int iocash; private Lock myLock;
    User(String name, MyCount myCount, int iocash, Lock myLock) { 
        this.name = name; this.myCount = myCount; this.iocash = iocash; this.myLock = myLock; 
    }
    public void run() {
        myLock.lock(); // 獲取鎖
        try {
            System.out.println(name + "正在操作" + myCount + "賬戶,金額為" + iocash + ",當前金額為" + myCount.getCash());
            myCount.setCash(myCount.getCash() + iocash);
            System.out.println(name + "操作" + myCount + "賬戶成功,金額為" + iocash + ",當前金額為" + myCount.getCash());
        } finally {
            myLock.unlock(); // 必須在 finally 中釋放!
        }
    }
}

class MyCount {
    private String oid; private int cash;
    MyCount(String oid, int cash) { this.oid = oid; this.cash = cash; }
    public int getCash() { return cash; }
    public void setCash(int cash) { this.cash = cash; }
    @Override public String toString() { return "MyCount{oid='" + oid + "', cash=" + cash + '}'; }
}

運行結果

張三正在操作MyCount{oid='95599200901215522', cash=10000}賬戶,金額為-4000,當前金額為10000
張三操作MyCount{oid='95599200901215522', cash=6000}賬戶成功,金額為-4000,當前金額為6000
張三他爹正在操作MyCount{oid='95599200901215522', cash=6000}賬戶,金額為6000,當前金額為6000
張三他爹操作MyCount{oid='95599200901215522', cash=12000}賬戶成功,金額為6000,當前金額為12000
張三他弟正在操作MyCount{oid='95599200901215522', cash=12000}賬戶,金額為-8000,當前金額為12000
張三他弟操作MyCount{oid='95599200901215522', cash=4000}賬戶成功,金額為-8000,當前金額為4000
張三正在操作MyCount{oid='95599200901215522', cash=4000}賬戶,金額為800,當前金額為4000
張三操作MyCount{oid='95599200901215522', cash=4800}賬戶成功,金額為800,當前金額為4800
Process finished with exit code 0

線程串行訪問賬戶,餘額變更正確(10000→6000→12000→4000→4800)。

關鍵最佳實踐

  1. lock/unlock 配對在 try/finally:防異常導致鎖永不釋放
  2. 縮小鎖範圍:僅鎖住共享狀態修改,業務邏輯、I/O 移出
  3. 選擇公平性:高爭用場景公平鎖減少饑餓,但吞吐較低
  4. 避免嵌套鎖:若需多鎖,統一獲取順序防死鎖

出處:https://lavasoft.blog.51cto.com/62575/222084

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved