2012-04-29 73 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