簡體   English   中英

Java Synchronized如何比較鎖定的對象?

[英]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鎖對象如此重要的原因。

當我們討論這個主題時,你也必須永遠不要像一個非最終對象(如BooleanInteger那樣同步一個可變值。 經常使用以下模式,這是非常錯誤的:

Boolean value = false;
...
// really bad idea
synchronized (value) {
   if (value) {
      value = false;
   } else {
      value = true;
   }
}

這是非常錯誤的,因為value引用正在改變。 因此,一個線程可能會鎖定它,然后更改它的引用值,以便另一個線程將鎖定另一個對象,並且兩個線程將同時在synchronized內。 更糟糕的是,因為使用Boolean值,只有2個truefalse值是常量,因此多個類將鎖定在相同的引用上。

你正在對一個對象進行同步,內存地址問題純粹是一個實現問題而不關心你。 只要它是相同的對象(意味着完全相同的實例),就完成了同步。

如果使用其他實例,則同步將不起作用。 你可以做的是將一個公共靜態常量定義為鎖:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM