2012-04-29 8 views
17

以下の2つのメソッドread()write()があります。javaメソッドの同期と読み取り/書き込みの相互排他

class Store 
{ 

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

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

1)Storeオブジェクトはシングルトンです。

2)私は店に書き込むWriterクラスと同時にストアから読み込むいくつかのReaderクラスを持っています。

私の要件は、ライターが店舗に書いているときに、すべての読者が待つ必要があるということです。すなわち、制御がwrite()である場合、read()へのすべての呼び出しをブロックすべきである。これをどのように達成するのですか?私はsynchronize(Store.class)write()メソッドで試しましたが、私にとってはうまくいかないようです。

+0

あなたは、クラスオブジェクト( 'synchronized(foo.class)')ではなく、あなたが操作しているインスタンス上で同期します。 – andersoj

答えて

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はインターフェイスです。 ;) –

+0

@Peter Lawrey:申し訳ありません。一定。 :) – Tudor

+4

@Tudor @ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ' 。 – matsev

0

はあなたが何を意味するかを説明する必要がありますので

3

​​が最も簡単な解決策であるjava.util.concurrentパッケージからReadWriteLockを使用するには「のための仕事のように見えるしていません。私はおそらくあなたがそれをどのように使用したかを見せてくれるでしょう。

ReentrantReadWriteLockを使用する方がよい場合は、リーダーに同時にアクセスできるためです。

2

あるオブジェクトでメソッドが同期されている場合、このメソッドを実行するスレッドは、同じオブジェクトで同期された別のブロック/メソッドを入力しようとする他のすべてのスレッドをブロックします。

したがって、書き込みスレッドが読み取りスレッドを禁止するようにするには、書き込みメソッドと読み取りメソッドの両方を同期させる必要があります。 Storeクラスで同期させる理由はありません。ストアオブジェクトで同期をとることは、より自然である:

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

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

これは、しかし、(多分)という欠点があります。それは同時に読み込むために、2つのリーダースレッドを禁止します。これが本当に必要な場合は、ReadWriteLockを使用してください。しかし、これはパフォーマンスの低いコードにつながり、理解して維持するのが難しくなります。私はこれが必要であると測定した場合にのみ使用します。

+0

なぜあなたは 'ReadWriteLock'が' synchronized'よりパフォーマンスが悪いと思いますか?両方のメソッドが単にセマフォ操作を指示する上位レベルのインタフェースでなければならないので、そのための良い技術的理由はありません。 – meustrus

+0

実際、 'ReentrantReadWriteLock'は' fair'ロックを使用しない限り、 'synchronized'よりも* better *を実際に実行するかもしれません。これは[同期とReentrantLockのIBMの比較](http://www.ibm.com/developerworks/java/library/j-jtp10264/)の結論の1つと思われます。 'ReentrantLock'は' ReentrantReadWriteLock'と同じではありませんが、読者をロックさせる必要はありません。 – meustrus

+0

このアプローチの問題は、読者がデータ構造を同時に読み取ることができないことです。多くの場合、これはまったく問題ではありません... –

関連する問題