Readers, writers concurrency problem

package concurency.locks;

import static java.lang.System.currentTimeMillis;
import static java.lang.System.out;
import static java.lang.Thread.currentThread;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class RWEx {

  final ReadWriteLock lock = new ReentrantReadWriteLock();

  void read(int limit) {
    lock.readLock().lock();
    try {
      doWithLimit("read", limit);
    } finally {
      lock.readLock().unlock();
    }
  }

  void write(int limit) {
    lock.writeLock().lock();
    try {
      doWithLimit("write", limit);
    } finally {
      lock.writeLock().unlock();
    }
  }

  void doWithLimit(String action, int limit) {
    for (int i = limit; i > 0; i--) {
      String thread = currentThread().getName();
      out.println(thread+","+action+",left "+i+sec());
      sleepSeconds(1);
    }
  }

  public static void main(String[] args) {
    RWEx rw = new RWEx();
    rw.createReader(rw, 3).start();
    sleepSeconds(1);
    rw.createReader(rw, 3).start();
    rw.createWriter(rw, 3).start();
  }

  Thread createWriter(final RWEx rwEx, final int limit){
    return new Thread(new Runnable() {

      @Override
      public void run() {
        rwEx.write(limit);
      }
    });
  }

  Thread createReader(final RWEx rwEx, final int limit){
    return new Thread(new Runnable() {

      @Override
      public void run() {
        rwEx.read(limit);
      }
    });
  }

  static void sleepSeconds(int n) {
    try {
      Thread.sleep(1000 * n);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

  static String sec() {
    long currentTimeMillis = currentTimeMillis();
    long value = currentTimeMillis / 1000;
    return ", second " + (value - (value / 100 * 100));
  }

}

Result:

// starting first reader

Thread-0,read,left 3, second 0
Thread-0,read,left 2, second 1

//starting second reader while first still running

Thread-1,read,left 3, second 1
Thread-0,read,left 1, second 2

// first reader finished, second still running

Thread-1,read,left 2, second 2
Thread-1,read,left 1, second 3

// second reader finished

// writer finally got exclusive access
// writer started

Thread-2,write,left 3, second 4
Thread-2,write,left 2, second 5
Thread-2,write,left 1, second 6

// writer finished

Note: each writer needs exclusive access for writing, readers can join reading readers.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s