【问题标题】:Synchronization pattern同步模式
【发布时间】:2012-02-03 19:12:38
【问题描述】:

我有一个名为“Channel”的类,定义了两个方法:

class Channel {

    void read(){...}
    void write(){...}
}

在多线程环境中使用了这个类的一个实例。几个线程周期性地从通道读取,而一个线程周期性地写入它。读取操作是线程安全的,因此可以同时发生多个读取。然而一旦写操作开始,读线程必须被阻塞直到写操作完成。必须尽可能快地保持读取操作并避免消耗资源的同步例程。

实现这种行为最合适的模式是什么?也许 java 类或库可以提供帮助?

【问题讨论】:

    标签: java concurrency


    【解决方案1】:

    使用ReadWriteLock。它将允许串行写入发生并发读取。为了进一步满足您的要求,购买writeLock 将阻止任何readLock 取得进展,直到后续发布。

    class Channel {
        final ReadWriteLock lock = new ReentrantReadWriteLock();
    
        void read(){
          lock.readLock().lock();
          try{
    
          }finally{
             lock.readLock().unlock();
          }
        }
        void write(){   
          lock.writeLock().lock();
          try{
    
          }finally{
             lock.writeLock().unlock();
          }
        }
    }
    

    【讨论】:

    • 也许在 Java 8 中,我们最终将拥有 try-with-resource :(
    • @stefan Java 7“确实”有这个功能,尽管它只适用于实现 AutoCloseable 的类。如果 Java 8 确实提供了闭包,那么这段代码看起来会好很多
    • 哦,亲爱的,我以为它被拿出来了。是时候去玩了:D
    【解决方案2】:

    为了好玩,这里有一个使用新的 Java 7 try-with-resources 特性的实现。

    class RWLock {
        class ACLock extends ReentrantLock implements AutoCloseable {
            public void close() {
                this.unlock();
            }
        }
    
        private ACLock readLock = ACLock();
        private ACLock writeLock = ACLock();
        private int numReaders = 0
    
        public AutoCloseable write() {
            readLock.lock();
            writeLock.lock();
            return new AutoCloseable() {
                public void close() {
                    writeLock.close();
                    readLock.close();
                }
            }
        }
    
        public AutoCloseable read() {
            try (ACLock read = readLock.acquire()) {
                if (numReaders == 0) {
                    writeLock.lock();
                }
                numReaders++;
            }
            return new AutoCloseable() {
                public void close() {
                    numReaders--;
                    if (numReaders == 0) {
                        writeLock.unlock();
                    }
                }
            }
        }
    
        // Here's how you use them
        public static void main(String[] args) {
            RWLock lock = RWLock();
            try (AutoCloseable lock = RWLock.read()) {
                // Do some readin'
            }
            try (AutoCloseable lock = RWLock.write()) {
                // Do some writin'
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-08-18
      • 1970-01-01
      • 2017-02-12
      • 1970-01-01
      • 1970-01-01
      • 2017-02-21
      • 2014-08-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多