读写锁ReentrantReadWriteLock:读读共享,读写互斥,写写互斥

介绍

DK1.5之后,提供了读写锁ReentrantReadWriteLock,读写锁维护了一对锁:一个读锁,一个写锁。通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升。在读多写少的情况下,读写锁能够提供比排他锁更好的并发性和吞吐量。

源码定义

/* 
* <p>This lock supports a maximum of 65535 recursive write locks
 * and 65535 read locks. Attempts to exceed these limits result in
 * {@link Error} throws from locking methods.
 *
 * @since 1.5
 * @author Doug Lea
 */
public class ReentrantReadWriteLock
        implements ReadWriteLock, java.io.Serializable {
    private static final long serialVersionUID = -6992448646407690164L;
    /** Inner class providing readlock */
    private final ReentrantReadWriteLock.ReadLock readerLock;
    /** Inner class providing writelock */
    private final ReentrantReadWriteLock.WriteLock writerLock;
    /** Performs all synchronization mechanics */
    final Sync sync;
    ...
}

 

code

public class ReentrantReadWriteLockTest {
    ReentrantReadWriteLock lock;
    private ReentrantReadWriteLock.ReadLock readLock;
    private ReentrantReadWriteLock.WriteLock writeLock;

    private ReentrantReadWriteLockTest() {
        lock = new ReentrantReadWriteLock();
        readLock = lock.readLock();
        writeLock = lock.writeLock();
    }

    public void read() {
        try {
            readLock.lock();
            System.out.println(Thread.currentThread().getName() + " 开始读了。。。");
            Thread.sleep(3000);
        }catch (InterruptedException e) {

        }finally {
            System.out.println(Thread.currentThread().getName() + " 读结束了。。。");
            readLock.unlock();
        }
    }

    public void write() {
        try {
            writeLock.lock();
            System.out.println(Thread.currentThread().getName() + " 开始写了。。。");
            Thread.sleep(3000);
        } catch (InterruptedException e) {

        } finally {
            System.out.println(Thread.currentThread().getName() + " 写完了。。。");
            writeLock.unlock();
        }
} }

测试1

 public static void main(String[] args) {
        final ReentrantReadWriteLockTest test = new ReentrantReadWriteLockTest();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.read();

            }
        }, "ReadThread1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.read();
            }
        }, "ReadThread2");
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.write();
            }
        }, "WriteThread1");
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.write();
            }
        }, "WriteThread4");

        t1.start();
        t2.start();
    }

输出

ReadThread1 开始读了。。。
ReadThread2 开始读了。。。
ReadThread1 读结束了。。。
ReadThread2 读结束了。。。

结论:读读共享  

测试2

t2.start();
t3.start();

输出

ReadThread2 开始读了。。。
ReadThread2 读结束了。。。
WriteThread1 开始写了。。。
WriteThread1 写完了。。。

结论:读写互斥

测试3

t4.start();
t3.start();

输出

WriteThread4 开始写了。。。
WriteThread4 写完了。。。
WriteThread1 开始写了。。。
WriteThread1 写完了。。。

结论:写写互斥

注意:新生成变量时,要用final修饰

final ReentrantReadWriteLockTest test = new ReentrantReadWriteLockTest();

原因:从内部类访问本地变量,本地变量要被声明为final类型

posted @ 2019-03-31 20:05  jihite  阅读(1065)  评论(0编辑  收藏  举报