2011-11-19 35 views
8

我有一個多線程應用程序使用提供列表的單個靜態類。我希望靜態類的getters能夠自由地工作(不同步),但是當setter工作時,我希望所有getter都被鎖定,並等待setter的工作完成。我不想鎖定getter,因爲它們會降低性能。吸氣劑每天被稱爲1,000,000次,吸氣器只應該每天工作一次。如何在setter在Java中工作時同步getter

+0

狀態變量? – Kris

回答

8

考慮使用java.util.concurrent.locks.ReadWriteLock實現,如ReentrantReadWriteLock(見javadoc

ReadWriteLock維護一對相關的鎖,一個用於只讀操作,另一個用於寫入的。只要沒有寫入器,讀取鎖可以由多個讀取器線程同時保存。寫鎖定是獨佔的。

你會用這個而不是​​。你的獲得者將獲得讀鎖,然後在他們返回時釋放,例如,

public String getX() { 
    Lock readLock = readWriteLock.readLock(); 
    readLock.lock(); 
    try { 
     return value; 
    } finally { 
     readLock.unlock(); 
    } 
} 

同樣對於setter方法,只是用readWriteLock.writeLock()來代替。

該類將有一個單獨的ReentrantReadWriteLock對象,由每個對象上的所有getter和setter共享(或者,如果願意,每個getter/setter對都有)。

這非常麻煩,但應該給予很好的併發性。由於這些原因,如果你真的需要它,你只應該採取這種方式,這意味着如果你只使用vanilla同步,就會測量你得到的降級併發性。

+0

偉大的方法,謝謝 –

6

您的設置人員可以在每次更新時獲取數據的副本,並且獲得者可以使用副本。這對於制定者來說可能非常昂貴,但對吸氣者的影響最小。

然而,同步鎖可能在25到100納秒的順序。即使您每分鐘調用一次同步方法一百萬次,​​也不會增加足夠的延遲時間。每秒一百萬,肯定會。

+0

好吧,那麼如果延遲順序爲ns我不介意只是同步所有的方法。感謝您的信息。 –

+0

您的第二段似乎不相關。 OP似乎並不擔心'synchronized'本身的開銷;相反,他只是不希望調用getter必須是順序的。 (我認爲你是對的,他不應該擔心;但不擔心的是吸氣劑應該是非常快速和便宜的,不是因爲「同步」。) – ruakh

+0

'synchronized'的成本通常遠高於調用getter的方法。如果你的吸氣器比這更昂貴,它不是一個常規的吸氣劑。 –

3

我會先同步所有訪問,並且只有在證明是性能問題時才進行優化。

要優化,可以使用CopyOnWriteArrayList或ReadWriteLock。如果不更準確地瞭解上下文,就很難給出明確的解決方案。

1

這是使用CopyOnWriteArrayList的原型案例。

「這通常代價太高,但在遍歷操作數量大大超過突變時可能會比替代方法更有效,而且當您不能或不想同步遍歷,但需要排除併發線程之間的干擾時,它非常有用。