24

我有两种方法read()write()如下所示。

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()方法,但似乎对我不起作用。

4

5 回答 5

41

在这种情况下,最好的选择是使用读写锁: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();
       }
    }
}
于 2012-04-29T13:59:55.097 回答
5

synchronized是最简单的解决方案,因此您应该解释“似乎不适合我”的意思,并可能向我们展示您是如何使用它的。

更好的解决方案是使用ReentrantReadWriteLock,因为它也允许对读取器进行并发访问。

于 2012-04-29T14:01:44.130 回答
3

当一个方法在某个对象上同步时,执行此方法的线程会阻塞所有其他尝试进入另一个在同一对象上同步的块/方法的线程。

因此,如果您希望写入器线程禁止任何读取器线程读取,则必须同步写入和读取方法。没有理由在Store课堂上进行同步。在对象上同步Store更自然:

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

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

然而,这(也许)有一个缺点:它还禁止两个读取器线程同时读取。如果你真的需要这样做,你应该使用ReadWriteLock。但这会导致代码性能降低,并且更难理解和维护。如果我测量到这是需要的,我只会使用它。

于 2012-04-29T14:05:54.143 回答
0

使用 java.util.concurrent 包中的 ReadWriteLock

于 2012-04-29T14:00:31.977 回答
0

请注意阅读这篇文章:

https://blog.takipi.com/java-8-stampedlocks-vs-readwritelocks-and-synchronized/

  • RWLocks 可能会很慢,尤其是当作者有很多读者时
  • 同步平均是最可靠的快速
  • 有像 StampedLock 这样的新锁
于 2018-08-30T19:04:28.773 回答