第一部分:併發理論基礎04->互斥鎖(下),如何用一把鎖保護多個資源
阿新 • • 發佈:2021-06-25
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.總結
理清多個資源的關係
資源之間沒關係,很好處理。每個資源一把鎖
資源之間有關係,選擇粒度更大的鎖,鎖要覆蓋所有相關的資源
原子性
本質其實是不可分割,多個資源一致性要求。中間狀態對外不可見
不能用可變物件做鎖