• 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();
                }
            }
        }
    }
  • 相关阅读:
    POI Excel解析
    mysql忘记root密码的解决方法
    注解实现AOP
    Java 集合类
    easyui-textbox 绑定事件
    MarqueeLabel 跑马灯
    Swift-2.14构造过程
    Swift-2.13继承
    Swift- 2.12下标脚本
    Swift-2.11方法
  • 原文地址:https://www.cnblogs.com/yaowen/p/11349128.html
Copyright © 2020-2023  润新知