2012-04-26 29 views

回答

4

只有方法本地的變量/引用。或者確保任何實例變量都是不可變的。

+0

不可變的實例變量是否可以接受? – duffymo 2012-04-26 09:48:25

+0

@duffymo編輯 – NimChimpsky 2012-04-26 09:50:16

+0

不錯 - 短而重要。 – 2016-11-18 12:16:16

4

如果沒有可變性,一切都是線程安全的,那麼可以通過使所有數據不可變,使您的代碼成爲線程安全的。其次,你可能想看看Java併發API,它提供了讀/寫鎖定的功能,以便在有很多讀者和一些作者的情況下執行更好。純同步關鍵字也會阻止兩位讀者。

7

實際上,很多方面:

  1. 無需同步在所有如果你沒有可變狀態。
  2. 如果可變狀態侷限於單個線程,則不需要同步。這可以通過使用局部變量或java.lang.ThreadLocal來完成。
  3. 您也可以使用內置同步器。 java.util.concurrent.locks.ReentrantLock與使用​​塊和方法訪問的鎖具有相同的功能,並且功能更強大。
+1

我更喜歡(2),但我不確定它是否可能在不使用'synchronized'關鍵字的情況下實現消息傳遞。我可以製作一個沒有「同步」的生產者 - 消費者隊列嗎? – 2012-04-26 10:07:17

+1

沒關係 - 我可以通過使用java.util.concurrent.Semaphore。 – 2012-04-26 10:10:06

+1

@MartinJames任何類似隊列和交換器的併發類都可以在沒有同步的情況下使用。 (他們使用Lock來代替)Disrupter支持不鎖定或同步的消息傳遞。 (我有一個庫,它也這樣做) – 2012-04-26 11:27:08

-2

爲什麼你需要這樣做?

僅使用本地變量/引用不會解決大多數複雜的業務需求。 另外,如果實例變量是不可變的,它們的引用仍然可以被其他線程改變。

其中一種選擇是使用類似於SingleThreadModel的東西,但非常不鼓勵和棄用。

ü也可以看看併發API通過卡爾

+0

「如果實例變量是不可變的,它們的引用仍然可以改變」不,它們不能 – NimChimpsky 2012-04-26 10:03:37

+0

可以解釋。我怎麼看它是如果我有一個instanace變量String s =「xyz」,我的thread1可以改變它的引用s =「abc」;和thread2現在會得到s =「abc」 – Kshitij 2012-04-26 10:08:15

+0

s是一個引用,它已經改變,它不是不可變的,你需要「最終字符串s」 – NimChimpsky 2012-04-26 10:11:51

1

上面建議保持預見性您必須確保所有訪問的可變數據由順序或處理由並行訪問的問題。

最嚴重的保護使用​​關鍵字。除此之外,至少有兩層可能性,每一層都有其優點。

鎖/信號燈

這些可以是非常有效的。例如,如果您的結構是由多個線程讀取的,但只能更新一個,則可能會發現ReadWriteLock有用。

如果您選擇鎖定來匹配算法,鎖定可以更加高效。

原子能

例如使用AtomicReference可以經常提供完全無鎖的功能。這通常可以提供巨大的好處。

原子背後的推理是讓他們失敗,但告訴你他們失敗的方式,你可以處理它。

例如,如果要更改某個值,則可以讀取該值,然後只要它仍舊是舊值就可以寫入新值。這被稱爲「比較和設置」或cas,通常可以在硬件中實現,因此非常有效。所有你需要的是這樣的:

long old = atomic.get(); 
while (!atomic.cas(old, old+1)) { 
    // The value changed between my get and the cas. Get it again. 
    old = atomic.get(); 
} 

但是,請注意,可預測性並不總是要求。