andrew.z
andrew.z

Reputation: 1059

Synchronization pattern

I have a class named "Channel" with two methods defined:

class Channel {

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

There's an instance of this class used in multi-threaded environment. Several threads periodically read from channel while one thread periodically writes to it. Read operation is thread-safe so that it is ok for several reads to occur simultaneously. However once write operation starts, read threads must be blocked until write operation is finished. It is essential to keep read operations as fast as possible and avoid resource-consuming synchronization routines.

What would be the most appropriate pattern to implement such behaviour? Maybe java classes or libraries to help?

Upvotes: 5

Views: 1837

Answers (2)

stefan
stefan

Reputation: 1559

For fun, here's an implementation using the new Java 7 try-with-resources feature.

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'
        }
    }
}

Upvotes: 1

John Vint
John Vint

Reputation: 40256

Use a ReadWriteLock. It will allow concurrent reads to occur with serial writes. To further satisfy your requirements, an acquisition of a writeLock will prevent any readLock's from making progress until a subsequent release.

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();
      }
    }
}

Upvotes: 8

Related Questions