[英]How can a thread acquire lock on two objects simultaneously as in this case?
public void method(Type1 inst1, Type2 inst2) {
synchronized(inst1) {
synchronized(inst2) {
//do something now
}
}
}
從這段代碼中我可以理解,一旦線程進入方法,它會先獲取inst1的鎖,然后再獲取inst2的鎖,而不釋放inst1的鎖。 我假設這兩個對象都沒有被其他線程鎖定。
1。 如果一個線程一次只能獲取一個對象的鎖,而當釋放當前對象的鎖時只能擁有另一個鎖,那么這段代碼如何有效?或者,我認為這是一個有效的代碼嗎?某處?
它是一個有效代碼時,鎖是不是其中該方法所在的對象上,但在inst1
和inst2
。 同樣,鎖不是在類上,而是在每個對象上
2。 如果Type1和Type2相同怎么辦?
同樣,鎖在對象上,而不在類上。 如果inst1和inst2相同,則該線程只有一個鎖,對於同一線程“重新輸入”鎖是有效的
3。 如果我們考慮到方法位於方法的參數類型之外的其他類中而使該方法同步,會發生什么情況?
然后,您還有另一個鎖,這次是在執行方法的對象(不是類)上。
由於@morgano和@Nick霍爾特 ,我明白, 一個線程可以保持在同一時間多個鎖 (不同的對象),或相同的對象上多次(使用獲得的鎖synchronized
是隱含地折返)。
如果您每次需要以相同的順序鎖定這兩個對象,則代碼沒有問題。
例如,如果您有兩種方法
public void methodA(Type1 inst1, Type2 inst2) {
synchronized(inst1) {
synchronized(inst2) {
//do something now
}
}
}
public void methodB(Type1 inst1, Type2 inst2) {
//wrong
synchronized(inst2) {
synchronized(inst1) {
//do something now
}
}
}
您有潛在的死鎖問題,因為線程可以獲取inst1上的鎖並等待inst2,而另一個線程具有inst2上的鎖並等待inst1上的鎖。
肯定的是,該代碼很可能會導致雷區陷入僵局。
鎖定inst2的第二個線程(threa2)不一定必須通過方法A運行,而是可以在另一個過程中鎖定對象inst2,並且在方法A中的線程1之前執行此操作,然后在釋放之前訪問方法A並嘗試鎖定inst2。 INST2。 AHHHHH! boooom! :(。
建議的解決方案:
與methodA同步,而不是在object上同步,因為那樣將鎖定在methodA()中訪問的所有資源,如下所示
公共同步void methodA(){....}
當您在另一個鎖中獲取一個鎖時會發生死鎖:
lock OB1 {
lock OB2 { ... }
}
因為人們可能會嘗試鎖定一對(1,2)
和花葯(2,1)
。 可能有更長的鏈: (1,2)
+ (2,3)
+ (3,1)
。
您需要在鎖之間引入順序以避免死鎖: Java 同步:跨帳戶對原子地轉移資金?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.