2012-04-29 108 views
17

我有兩個方法read()write()在一個類如下所示。java方法同步和讀/寫互斥

class Store 
{ 

    public void write() 
    { 
    // write to store; 
    } 

    public string read() 
    { 
    // read from store; 
    } 
} 

1)Store對象是一個單例。

2)我有一個Writer類,它將寫入商店和幾個Reader類,它們將同時從商店中讀取。

我的要求是當作者寫信給商店時,所有的讀者都應該等待。即,當控制在write()中時,應該阻止對read()的所有呼叫。我如何實現這一目標?我在write()方法中嘗試過synchronize(Store.class),但似乎不適合我。

+0

你不想在類對象('synchronized(foo.class)')上同步,而是在你正在操作的實例上進行同步。 – andersoj 2012-05-01 02:13:35

回答

33

這種情況下的最佳選擇是使用讀寫器鎖:ReadWriteLock。它允許一個作者,但多個併發讀者,所以它是這種情況下最有效的機制。

一些示例代碼:

class Store 
{ 
    private ReadWriteLock rwlock = new ReentrantReadWriteLock(); 

    public void write() 
    { 
     rwlock.writeLock().lock(); 
     try { 
      write to store; 
     } finally { 
      rwlock.writeLock().unlock(); 
     } 
    } 

    public String read() 
    { 
     rwlock.readLock().lock(); 
     try { 
      read from store; 
     } finally { 
      rwlock.readLock().unlock(); 
     } 
    } 
} 
+0

ReadWriteLock是一個接口。 ;) – 2012-04-29 14:02:54

+0

@Peter Lawrey:對不起。固定。 :) – Tudor 2012-04-29 14:03:34

+4

@Tudor您應該總是將_read存儲_和_write存儲到_try_塊中的store_操作,並確保在相應的_finally_塊中包含您的unlock()方法,以防止發生異常時鎖保持鎖定狀態。 – matsev 2012-04-29 14:07:38

0

從java.util.concurrent包使用ReadWriteLock中

3

​​是最簡單的解決方案,因此,你應該解釋一下你的意思是「似乎並不喜歡的工作我「,也許告訴我們你是如何使用它的。

更好的解決方案是使用ReentrantReadWriteLock,因爲它允許同時訪問讀者。

2

當某個方法在某個對象上同步時,執行此方法的線程會阻止所有其他線程嘗試進入另一個在同一對象上同步的塊/方法

因此,如果您希望寫入程序線程禁止任何讀取器線程讀取,則必須同步寫入和讀取方法。沒有理由在Store類上同步。同步存儲對象上更自然:

public synchronized void write() { 
    write to store; 
} 

public synchronized String read() { 
    read from store; 
} 

然而,這(也許)有一個缺點:它也禁止2個閱讀器線程在同一時間閱讀。如果您真的需要這樣做,您應該使用ReadWriteLock。但是這會導致代碼性能降低,難以理解和維護。如果我已經測量過這是必要的,我只會使用它。

+0

爲什麼你會說'ReadWriteLock'的性能比'synchronized'低?沒有好的技術理由,因爲這兩種方法應該只是一個更高級別的接口來指導信號操縱。 – meustrus 2014-05-23 18:56:22

+0

事實上,只要您不使用「公平」鎖,「ReentrantReadWriteLock」看起來可能會比'synchronized'更好*。這似乎是[這個IBM'synchronized'和'ReentrantLock'之間的比較]的結論[http://www.ibm.com/developerworks/java/library/j-jtp10264/]。儘管「ReentrantLock」與「ReentrantReadWriteLock」並不相同,但如果不需要,爲什麼要鎖定讀者呢? – meustrus 2014-05-23 19:08:35

+0

這種方法的問題是讀者不能同時讀出數據結構,而在很多情況下,這根本不是問題...... – 2014-09-02 14:55:31