• ReentrantReadWriteLock的使用


    ReentrantReadWriteLock的规则是:

    多线程情况下:读-写互斥、写-读互斥、写-写互斥、读-读共享

    验证“读-写互斥、写-读互斥、写-写互斥、读-读共享”

          //单个线程 读-读 不互斥
            r.lock();
            r.lock();
            System.out.println("读-读 不互斥");
            r.unlock();
            r.unlock();
            //多个线程 读-读 不互斥
            new Thread(() -> {
                r.lock();
                try {Thread.sleep(2000L);} catch (InterruptedException e) {}
                r.unlock();
            }).start();
            new Thread(() -> {
                r.lock();
                System.out.println("立刻执行");
                r.unlock();
            }).start();
            //单个线程 读-写 互斥,不存在锁升级
            r.lock();
            w.lock();
            System.out.println("ok");
            w.unlock();
            r.unlock();
           //多个线程 写-读 互斥
            new Thread(() -> {
                w.lock();
                try {Thread.sleep(10000000L);} catch (InterruptedException e) {}
                w.unlock();
            }).start();
            try {Thread.sleep(500L);} catch (InterruptedException e) {}//等第一个线程
            new Thread(() -> {
                r.lock();
                System.out.println("我能获得读锁");
                r.unlock();
            }).start();
            

    ReentrantReadWriteLock使用场景

    对于数据比较敏感的场景,

    读锁:在读取数据时是不能出现多次读取不一致的情况的,这点有点像可重复读和幻读,

    写锁:写数据时,又不能同时读取数据

       private final Map<String, Data> m = new TreeMap<String, Data>();
        private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
        private final Lock r = rwl.readLock();
        private final Lock w = rwl.writeLock();
    
        public Data get(String key) {
            r.lock();
            try { return m.get(key); }
            finally { r.unlock(); }
        }
        public String[] allKeys() {
            r.lock();
            try { return m.keySet().toArray(); }
            finally { r.unlock(); }
        }
        public Data put(String key, Data value) {
            w.lock();
            try { return m.put(key, value); }
            finally { w.unlock(); }
        }
        public void clear() {
            w.lock();
            try { m.clear(); }
            finally { w.unlock(); }
        }

     锁降级

    单线程情况下有个特殊的点:读-写不互斥、即降级

     //单个线程 写-读 不互斥,降级
            w.lock();
            r.lock();
            System.out.println("ok");
            r.unlock();
            w.unlock();
    //降级后,其他线程读不能进来 因为写锁并没有完全释放,如果按照下面这种方式做,那么降级将变的没有任何意义,因为你完全可以用一把写锁就代替了
            new Thread(() -> {
                w.lock();
                r.lock();
                System.out.println("我已经降级了");
                try {Thread.sleep(2000L);} catch (InterruptedException e) {}
                r.unlock();
                w.unlock();
            }).start();
            new Thread(() -> {
                r.lock();
                System.out.println("我能进去");
                r.unlock();
            }).start();
    //正确的姿势如下,这样就能保证在写锁没释放前转化为读锁,写锁紧接着释放,其他线程的读就可以进去了
    new Thread(() -> {
        w.lock();
        r.lock();
        w.unlock();
        System.out.println("我已经降级了");
        try {Thread.sleep(2000L);} catch (InterruptedException e) {}
        r.unlock();
    }).start();
    new Thread(() -> {
        r.lock();
        System.out.println("我能进去");
        r.unlock();
    }).start();

    锁降级可以帮助我们拿到当前线程修改后的结果而不被其他线程所破坏

    锁降级的典型用法

     private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
     private final Lock r = rwl.readLock();
     private final Lock w = rwl.writeLock();
    
    w.lock();
    //writing
    r.lock();
    w.unlock();
    //reading
    r.unlock();

  • 相关阅读:
    项目ITP(五) spring4.0 整合 Quartz 实现任务调度
    [Git 系列] WIN7下Git的安装
    Candy
    OSGI
    JAVA编程思想(1)
    [python] 字典和列表中的pop()函数
    R语言编程语法
    Linux 之创建工作目录-mkdir
    python 之 改变工作目录
    python 之 'and' 和 'or'
  • 原文地址:https://www.cnblogs.com/zxporz/p/10874853.html
Copyright © 2020-2023  润新知