簡體   English   中英

同步關鍵字-如何運作?

[英]Synchronized keyword- how it works?

如果我有一個類,則稱它X並且X包含一個集合(假設我沒有使用同步集合之一,只是一個普通集合)。

如果要編寫自己的方法,則同步的add()-鎖定如何工作? 鎖定是否在X實例上完成,而不在集合對象上完成?

因此,同步我的add()方法不會阻止X的許多實例調用add()並將其插入集合中-因此,我仍然可能遇到線程問題嗎?

同步方法鎖定對象。 如果您的X.add是同步的,它將阻止並發執行同一X對象的其他同步方法。 如果該X對象之外的任何人都可以訪問同一集合,則該集合將不受保護。

如果要保護您的集合,請確保除X的同步方法外,其他任何地方都無法訪問它。 此外,這在您的問題中還不清楚,但是請注意,同步的非靜態方法會鎖定對象 假設每個X實例都有自己的集合,它們不會互相干擾。

另一個選項BTW是鎖定集合而不是X對象:

void add(Object o) {
   synchronized(myCollection) {
      myCollection.add(o);
   }
}

這將同步對鎖定集合而不是X對象的訪問。 使用任何您發現更容易有效的方法。

在您的示例中, synchronized將確保一次只能有一個線程可以在該類的一個實例上調用該方法。 其他方法可以訪問該集合,這將是不安全的。 查找並發集合以獲取有關線程安全集合實現的更多信息。

如果要編寫自己的方法,則同步的add()-鎖定如何工作? 鎖定是否在X實例上完成,而不在集合對象上完成?

鎖定是在您同步的對象上完成的,而不是對象內的任何字段。 為了使鎖定起作用,所有線程必須在同一確切對象上同步。 通常,最好將private final對象鎖定。

    private final Collection<...> myCollection = ...
    ...
    synchronize (myCollection) {
        myCollection.add(...);
    }

盡管常見的模式是鎖定要保護的對象,但實際上它可以是任何常量對象。 您也可以這樣做:

    private final Object lockObject = new Object();
    ...
    synchronize (lockObject) {
        myCollection.add(...);
    }

因此,同步我的add()方法不會阻止X的許多實例調用add()並將其插入集合中-因此,我仍然可能遇到線程問題嗎?

如果應用程序的其他部分正在訪問myCollection 而不位於synchronized (myCollection)塊內部,則可以,您將遇到線程問題。 您需要圍繞所有訪問進行同步,以正確保護集合並提供內存屏障。 這意味着add(...)contains(...) ,迭代器等。

通常,如果您試圖保護集合或其他類,則將其包裝在進行同步的類中是很有意義的。 這將隱藏鎖定,並保護集合免受丟失synchronized塊的代碼的意外修改。

您是否在多個X實例上共享一個集合 ,這是真的嗎? 然后,您需要在集合實例本身上進行同步。 不要使方法本身synchronized ,而是將其所有代碼包裝在synchronized(coll) { ... }塊中。

另一方面,如果每個X都有自己的集合,那么您只需要synchronized add() 這將確保沒有兩個線程同時在同一實例上執行add

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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