ReentrantReadWriteLock源码分析

代码在后面

 

读锁 = 共享锁

读锁写锁,公用一个Sync AQS state

 

写锁是排他的,看到有人获取锁,他不会去获取,他获取了锁别人也不会进来获取锁。

写锁的获取跟ReentarntLock一样,每次加1,是一个独占锁,只要有人获取了锁,自己就去排队,排队时候节点是EXCLUSIVE的节点,入队方法acquireQueuedReentarntLock一样,会设置OwnerThread

 

读锁先获取锁,后面有读锁进来,多个读线程共存时候,第一个读线程设置firstReader其余读线程设置threadLocals属性,然后获取锁,读锁每次增加65536

写锁再进来,就去排队。

读锁再又进来,读锁还是去排队,

 

读锁不会设置OwnerThread只是会state增加65536,写锁会忽略大于65536的部分。

state!=0,state去掉前16=0,说明有读锁进去,写锁不进去

 

State高位存储读锁获取次数,低位存储写锁获取次数。

 

设置threadLocals属性的读线程unlock时候清除threadLocalMap的标记,设置firstReader的读线程unlock时候设置firstReader=null,并且state65536

 

//读锁进来,首先判断state后16位,有写锁就去排队,没有写锁就设置firstReader或者firstReaderHoldCount++或者当前线程的threadLocals并且state增加65536
//写锁进来时候,首先判断state,有读锁写锁就去排队,

1.读锁进来,不看owenerThread,看的是state,去掉前面16=0,说明没有写线程获取锁,就设置firstReader或者threadLocalMapstate增加65536state去掉前面16!=0说明有写线程获得了锁,就去排队。如果队列第一个是写线程,就去排队。 如果后面还有读线程进来,照样。

2.写锁进来,state!=0,state去掉前面16=0,说明state已经加了几个65536了,说明有线程在读,写锁要去排队。state=0说明没有写线程获取锁,没有读线程在读,就去获取锁。state!=0,state去掉前面16!=0,说明state有写线程获取锁,就去排队。

 

读锁每次加65536,不设置owenerThread。写锁每次加1,设置owenerThread

 

读:去掉前面16!=0就去排队,队列空设置firstReader或者threadLocalMap第一个节点是写线程排队,第一个节点是读线程设置firstReader或者threadLocalMap

 

写:state!=0,去掉前面16=0去排队,state=0获取锁。

 

 

if (exclusiveCount(c) != 0 /*去掉前面16位,*/ && getExclusiveOwnerThread() != current)

获取读锁时候,去掉前面16位!=0,OwnerThread() = current,说明里面有写锁了,并且是自己。说明一个线程先获取写锁在获取读锁,那么这个线程占据了owenerThreadfirstReader或者threadLocalMap

 

public class ReadWriteLockTest<E> {
    private final Map<String, String> map = new TreeMap<>();
    private final ReentrantReadWriteLock1 lock = new ReentrantReadWriteLock1();
    //写的时候,不能读不能写。 读的时候,不能写可以读。
    
    //读线程获取锁,其他读线程可以获取锁,写线程不能获取锁
    //写线程获取锁,读线程写线程不能获取锁
    private final ReentrantReadWriteLock1.ReadLock readLock = lock.readLock();
    private final ReentrantReadWriteLock1.WriteLock writeLock = lock.writeLock();

    public ReadWriteLockTest() {
    }

    public  String write(String key, String value) throws InterruptedException {
        writeLock.lock();//写锁是排他的,看到有人获取锁,他不会去获取,他获取了锁别人也不会进来获取锁。
        readLock.lock();
//        writeLock.lockInterruptibly();
//        writeLock.tryLock();
        try {
            return map.put(key, value);
        } finally {
            writeLock.unlock();//写锁释放,就唤醒AQS
        }
    }
 
    public String read(String key) throws InterruptedException {
        readLock.lock();//获取的是共享锁
//        writeLock.lock();
//        readLock.lockInterruptibly();
//        readLock.tryLock();
        try {
            return map.get(key);
        } finally {
            readLock.unlock();//读锁全部释放完了,才会去唤醒AQS
        }
    }

    private static ReadWriteLockTest<Integer> tt = new ReadWriteLockTest<Integer>();

    public static void main(String[] args) {
        new Thread(() -> {
            int i = 0;
            while (true) {
                Write w = new Write("写--" + (i++));
                w.start();
            }
        }).start();

        new Thread(() -> {
            int j = 0;
            while (true) {
                Read s1 = new Read("读--" + (j++));
                s1.start();
//                Read s2 = new Read("读--" + (j++));
//                s2.start();
//                Read s3 = new Read("读--" + (j++));
//                s3.start();
//                s1.interrupt();
//                s2.interrupt();
//                s3.interrupt();
            }
        }).start();
    }
    static int i =0;static int j = 0;
    static class Write extends Thread {
        Write(String name) {
            super(name);
        }
        @Override
        public void run() {
            try {
                tt.write((i++)+"",(j++)+"");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class Read extends Thread {
        Read(String name) {
            super(name);
        }
        @Override
        public void run() {
            try {
                tt.read((i--)+"");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 

posted @ 2019-08-13 22:52  无天666  阅读(256)  评论(0编辑  收藏  举报