javamultithreadingconcurrencyreentrantreadwritelock

Does ReentrantReadWriteLock read while writeLock locked?


I research ReentrantReadWriteLock.

I write simple code for test(I know that use Thread.sleep() can not guarantee predictable result but I think that I am lucky:)):

public class RWLock {
    private static String val = "old";
    private static ReadWriteLock lock = new ReentrantReadWriteLock();
    private static long time =  System.currentTimeMillis();
    public void read() {
        try {
            lock.readLock().lock();
            System.out.println("read " + val +" - "+(System.currentTimeMillis()-time));
            Thread.sleep(300);
        } catch (InterruptedException e) {

        } finally {
            lock.readLock().unlock();
        }
    }

    public void write() {
        try {
            lock.writeLock().lock();
            val = "new";
            System.out.println("write " + val+" - "+(System.currentTimeMillis()-time));
            Thread.sleep(10000);
        } catch (InterruptedException e) {

        } finally {
            lock.writeLock().unlock();
        }
    }
}

class Tester {
    public static void main(String[] args) throws InterruptedException {

        new MyThreadRead().start();

        Thread.sleep(400);
        new MyThreadWrite().start();
    }

}

class MyThreadRead extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            new RWLock().read();
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
            }
        }
    }
}

class MyThreadWrite extends Thread {
    @Override
    public void run() {
        new RWLock().write();
    }
}

output:

read old - 0
write new - 401
read new - 10401
read new - 10902
read new - 11402
read new - 11902
read new - 12402
read new - 12902
read new - 13402
read new - 13902
read new - 14402

10401 - 401 == 10000

10000 it is time of writing.

As I understood second read thread cannot finish before writing. Thus writing and second reading performs in parallel. It is not predictable behaviour for me.

What do you think about it?


Solution

  • Maybe you have more sleep() calls than you realize. The sleep calls in MyThreadRead#run() and in RWLock()#read() add up to 500 ms. So here's what's happening.

    At T=0, the reader thread grabs the read lock and sleeps for 300ms.
    At T=300, the reader releases the lock, and then sleeps for another 200ms.
    At T=400, the writer grabs the write lock and sleeps for ten seconds,
    At T=500, the reader tries to grab the read lock, but it is blocked by the writer.
    At T=10400, the writer gives up the lock, and then the reader gets to go round
       its loop nine more times.
    

    P.S.: Move your lock() calls out of the try/finally statements. E.g.,

    ...lock()
    try {
        ...
    } finally {
        ...unlock();
    }
    

    That way, if the lock() call throws an exception, the unlock() will not be called.