【问题标题】:java method synchronization and read/write mutual exclusionjava方法同步和读/写互斥
【发布时间】:2012-04-29 13:57:50
【问题描述】:

我在一个类中有两个方法read()write(),如下所示。

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),但似乎不适合我。

【问题讨论】:

  • 您不想在类对象 (synchronized (foo.class)) 上同步,而是在您正在操作的实例上同步。

标签: java multithreading concurrency


【解决方案1】:

在这种情况下,最好的选择是使用读写锁: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();
       }
    }
}

【讨论】:

  • ReadWriteLock 是一个接口。 ;)
  • @Peter Lawrey:很抱歉。固定的。 :)
  • @Tudor 您应该始终将 read to storewrite to store 操作包装在 try 块中并制作确保在相应的 finally 块中包含 unlock() 方法,以防止在发生异常时锁保持锁定状态。
  • @vijvij123:如果它解决了您的问题,请不要忘记回来接受答案。 :)
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

    public synchronized void write() {
      write to store;
    }
    
    public synchronized String read() {
      read from store;
    }
    

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

    【讨论】:

    • 为什么你会说ReadWriteLock 的性能不如synchronized?这样做没有什么好的技术理由,因为这两种方法都应该只是一个更高级别的接口来指导信号量操作。
    • 事实上,只要您不使用“公平”锁,ReentrantReadWriteLock 的性能实际上可能比synchronized 更好。这似乎是this IBM comparison between synchronized and ReentrantLock 的一个结论。尽管ReentrantLockReentrantReadWriteLock 不同,这毫无价值,但如果非必要,你为什么要把读者拒之门外呢?
    • 这种方式的问题是读者不能同时读出数据结构,而在很多情况下,这根本不是问题……
    【解决方案4】:

    使用 java.util.concurrent 包中的 ReadWriteLock

    【讨论】:

      【解决方案5】:

      请仔细阅读这篇文章:

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

      • RWLocks 可能会很慢,尤其是当写入者有很多读取器时
      • 同步平均是最可靠的快速
      • 有像 StampedLock 这样的新锁

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-16
        • 1970-01-01
        • 1970-01-01
        • 2012-12-29
        • 2012-04-23
        • 2011-06-10
        相关资源
        最近更新 更多