1. 程式人生 > 其它 >第一部分:併發理論基礎04->互斥鎖(下),如何用一把鎖保護多個資源

第一部分:併發理論基礎04->互斥鎖(下),如何用一把鎖保護多個資源

1.一把鎖保護多個資源

受保護資源和鎖的關係是N:1

2.保護沒有關聯關係的多個資源

銀行業務中針對賬戶餘額的取款操作
銀行業務中針對賬戶密碼的更改操作
為賬戶餘額和密碼修改分配不同的鎖來解決併發問題

程式碼,兩把鎖ballLock,pwLock分別保護不同的資源


class Account {
  // 鎖:保護賬戶餘額
  private final Object balLock
    = new Object();
  // 賬戶餘額  
  private Integer balance;
  // 鎖:保護賬戶密碼
  private final Object pwLock
    = new Object();
  // 賬戶密碼
  private String password;

  // 取款
  void withdraw(Integer amt) {
    synchronized(balLock) {
      if (this.balance > amt){
        this.balance -= amt;
      }
    }
  } 
  // 檢視餘額
  Integer getBalance() {
    synchronized(balLock) {
      return balance;
    }
  }

  // 更改密碼
  void updatePassword(String pw){
    synchronized(pwLock) {
      this.password = pw;
    }
  } 
  // 檢視密碼
  String getPassword() {
    synchronized(pwLock) {
      return password;
    }
  }
}

用不同的鎖保護資源進行精細化管理,能夠提升效能,這叫做細粒度鎖

3.保護有關聯關係的多個資源

例如轉賬操作,賬戶A減少100,賬戶B增加100

不能用自己家的鎖,保護別人家的大門一樣

4.使用鎖的正確姿勢

一把鎖保護多個資源
很簡單,A,B兩個賬戶用的是一把鎖就好了

如何一把鎖,什麼套路?
(1)2個Account物件都持有一個唯一的物件,這個物件再Account生成時傳入


class Account {
  private Object lock;
  private int balance;
  private Account();
  // 建立Account時傳入同一個lock物件
  public Account(Object lock) {
    this.lock = lock;
  } 
  // 轉賬
  void transfer(Account target, int amt){
    // 此處檢查所有物件共享的鎖
    synchronized(lock) {
      if (this.balance > amt) {
        this.balance -= amt;
        target.balance += amt;
      }
    }
  }
}

(2)對Account.class類檔案加鎖


class Account {
  private int balance;
  // 轉賬
  void transfer(Account target, int amt){
    synchronized(Account.class) {
      if (this.balance > amt) {
        this.balance -= amt;
        target.balance += amt;
      }
    }
  } 
}

5.總結

理清多個資源的關係
資源之間沒關係,很好處理。每個資源一把鎖
資源之間有關係,選擇粒度更大的鎖,鎖要覆蓋所有相關的資源

原子性
本質其實是不可分割,多個資源一致性要求。中間狀態對外不可見
不能用可變物件做鎖