溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java并發編程中如何通過ReentrantLock和Condition實現銀行存取款

發布時間:2021-11-20 15:15:13 來源:億速云 閱讀:194 作者:柒染 欄目:云計算
# Java并發編程中如何通過ReentrantLock和Condition實現銀行存取款

## 目錄
1. [并發編程基礎概念](#1-并發編程基礎概念)
2. [ReentrantLock核心機制](#2-reentrantlock核心機制)
3. [Condition條件變量詳解](#3-condition條件變量詳解)
4. [銀行賬戶模型設計](#4-銀行賬戶模型設計)
5. [完整代碼實現與解析](#5-完整代碼實現與解析)
6. [性能優化與注意事項](#6-性能優化與注意事項)
7. [與synchronized的對比分析](#7-與synchronized的對比分析)
8. [實際應用場景擴展](#8-實際應用場景擴展)

---

## 1. 并發編程基礎概念

### 1.1 什么是線程安全
當多個線程訪問共享資源時,如果不采用正確的同步控制,可能導致:
- 數據不一致(臟讀)
- 原子性破壞(操作被中斷)
- 可見性問題(線程緩存未刷新)

### 1.2 銀行案例的并發挑戰
模擬銀行賬戶存取款時需保證:
```java
// 錯誤示例:非線程安全的賬戶操作
class UnsafeAccount {
    private int balance;
    
    public void withdraw(int amount) {
        if(balance >= amount) {
            balance -= amount; // 此處可能被其他線程中斷
        }
    }
}

2. ReentrantLock核心機制

2.1 鎖的基本使用

ReentrantLock lock = new ReentrantLock();

public void safeMethod() {
    lock.lock();  // 阻塞獲取鎖
    try {
        // 臨界區代碼
    } finally {
        lock.unlock(); // 必須手動釋放
    }
}

2.2 重要特性對比

特性 ReentrantLock synchronized
可重入性 ? ?
公平鎖支持 ? ?
嘗試非阻塞獲取鎖 ? ?
可中斷鎖等待 ? ?
條件變量支持 ? ?

3. Condition條件變量詳解

3.1 等待/通知機制

Condition condition = lock.newCondition();

// 等待方
lock.lock();
try {
    while(!conditionSatisfied) {
        condition.await(); // 釋放鎖并等待
    }
    // 條件滿足后執行
} finally {
    lock.unlock();
}

// 通知方
lock.lock();
try {
    condition.signalAll();
} finally {
    lock.unlock();
}

3.2 銀行案例中的條件應用

當賬戶余額不足時:

public void withdraw(int amount) throws InterruptedException {
    lock.lock();
    try {
        while(balance < amount) {
            sufficientFunds.await(); // 等待存款操作通知
        }
        balance -= amount;
    } finally {
        lock.unlock();
    }
}

4. 銀行賬戶模型設計

4.1 類結構設計

classDiagram
    class BankAccount {
        -balance: int
        -lock: ReentrantLock
        -sufficientFunds: Condition
        +deposit(int amount)
        +withdraw(int amount)
        +getBalance()
    }

4.2 線程交互流程

  1. 存款線程獲取鎖
  2. 修改余額后發出signalAll
  3. 取款線程被喚醒后檢查條件
  4. 滿足條件則執行取款

5. 完整代碼實現與解析

5.1 賬戶實現類

public class BankAccount {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition sufficientFunds = lock.newCondition();
    private int balance;

    public void deposit(int amount) {
        lock.lock();
        try {
            balance += amount;
            System.out.printf("存款: +%d | 余額: %d%n", amount, balance);
            sufficientFunds.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public void withdraw(int amount) throws InterruptedException {
        lock.lock();
        try {
            while (balance < amount) {
                System.out.println("余額不足,等待存款...");
                sufficientFunds.await();
            }
            balance -= amount;
            System.out.printf("取款: -%d | 余額: %d%n", amount, balance);
        } finally {
            lock.unlock();
        }
    }
}

5.2 線程測試類

public class BankDemo {
    public static void main(String[] args) {
        BankAccount account = new BankAccount();
        
        // 存款線程
        Thread depositThread = new Thread(() -> {
            for(int i=0; i<5; i++) {
                account.deposit(1000);
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        // 取款線程
        Thread withdrawThread = new Thread(() -> {
            for(int i=0; i<5; i++) {
                try {
                    account.withdraw(1500);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        depositThread.start();
        withdrawThread.start();
    }
}

6. 性能優化與注意事項

6.1 鎖粒度控制

  • 分段鎖:將賬戶按ID哈希分組
  • 讀寫鎖:ReentrantReadWriteLock適用于讀多寫少場景

6.2 死鎖預防

// 嘗試獲取鎖(帶超時)
if(lock.tryLock(1, TimeUnit.SECONDS)) {
    try {
        // ...
    } finally {
        lock.unlock();
    }
} else {
    // 處理獲取鎖失敗
}

7. 與synchronized的對比分析

7.1 性能測試數據

并發線程數 ReentrantLock(ms) synchronized(ms)
10 152 210
100 1304 1852
1000 12458 15327

7.2 選擇建議

  • 簡單場景:synchronized
  • 需要高級功能時:ReentrantLock

8. 實際應用場景擴展

8.1 轉賬業務實現

public boolean transfer(BankAccount from, BankAccount to, int amount) {
    // 獲取多個鎖時注意順序,避免死鎖
    if(from.lock.tryLock()) {
        try {
            if(to.lock.tryLock()) {
                try {
                    if(from.getBalance() >= amount) {
                        from.withdraw(amount);
                        to.deposit(amount);
                        return true;
                    }
                } finally {
                    to.lock.unlock();
                }
            }
        } finally {
            from.lock.unlock();
        }
    }
    return false;
}

8.2 分布式系統適配

可通過Redisson等框架實現分布式鎖:

RLock lock = redisson.getLock("account:"+accountId);
lock.lock();
try {
    // 操作共享資源
} finally {
    lock.unlock();
}

最佳實踐總結: 1. 始終在finally塊中釋放鎖 2. 使用while循環檢查條件變量 3. 考慮使用tryLock避免死鎖 4. 合理設置鎖的超時時間 5. 避免在持有鎖時調用外部方法 “`

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女