[英]How do determine if an object is locked (synchronized) so not to block in Java?
[英]How does Java Synchronized compare locked objects?
我想在多個API請求上鎖定一個對象,這樣每個用戶只能輸入一個代碼塊。
synchronized(obj)
是否基於對象的引用或其hashCode()
函數進行鎖定?
我可以這樣做:
synchronized("asdf") {
doSomethingNifty();
}
這里“asdf”有一個唯一的哈希,但沒有唯一的引用。
synchronized(obj)是否基於對象的內存位置或其toHash()函數進行鎖定?
都不是。 它鎖定在與對象關聯的監視器上。 就JVM而言,我們不討論對象的內存地址,因為它是可重定位的,並且它不是哈希代碼(即使在Object.hashcode()
),因為它不是唯一的。
就你應該鎖定的內容而言,它應該是相同的final
對象。 就像是:
private final Object lockObject = new Object();
...
synchronized (lockObject) {
// do stuff that needed to be protected
}
您希望它是final
以便可以保證多個線程鎖定在不更改的同一對象引用上。 private
是好的,所以外面的類不能搞砸類內部的鎖定。
這里“asdf”具有唯一的哈希,但沒有唯一的內存地址。
"asdf"
不具有唯一性哈希,因為其他字符串可能具有相同的哈希值,它實際上可以在應用程序中有一個獨特的“內存地址”跨越“ASDF”的所有用法如果編譯器將其存儲在Java字符串池 。 這意味着一些完全不同的類也可能具有相同的壞模式代碼塊,並且會影響類的同步,因為它將鎖定在同一個String
對象實例上。 這就是private
鎖對象如此重要的原因。
當我們討論這個主題時,你也必須永遠不要像一個非最終對象(如Boolean
或Integer
那樣同步一個可變值。 經常使用以下模式,這是非常錯誤的:
Boolean value = false;
...
// really bad idea
synchronized (value) {
if (value) {
value = false;
} else {
value = true;
}
}
這是非常錯誤的,因為value
引用正在改變。 因此,一個線程可能會鎖定它,然后更改它的引用值,以便另一個線程將鎖定另一個對象,並且兩個線程將同時在synchronized
內。 更糟糕的是,因為使用Boolean
值,只有2個true
和false
值是常量,因此多個類將鎖定在相同的引用上。
你正在對一個對象進行同步,內存地址問題純粹是一個實現問題而不關心你。 只要它是相同的對象(意味着完全相同的實例),就完成了同步。
如果使用其他實例,則同步將不起作用。 你可以做的是將一個公共靜態常量定義為鎖:
public final static Object LOCK = new Object();
並使用它
synchronized(SomeClass.LOCK) {
鎖定在對象本身的實例上,如果您想這樣想,可以將其視為內存位置。 所以你的建議是行不通的。
相反,聽起來你只需要一個對應於你想要保護的代碼塊的單個對象。 因此,在程序的設置過程中,您需要類似的東西
static Object lockObject = new Object();
然后你就可以做到
synchronized(lockObject) {
doSomethingNifty();
}
但是,如果doSomethingNifty()與特定對象相關,那么使用該對象而不是lockObject會很有意義。 還要確保doSomethingNifty()快速執行,否則會有很多用戶等待。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.