并发编程之读写锁特性及ReentrantReadWriteLock的使用

谁说胖子不能爱 提交于 2020-01-23 19:36:59

读写锁特性:
多个线程的操作中,写写互斥、读写互斥、读读共享

新建一个ReetrantReadWriteLock的类,一个输出的方法,一个变量自增的方法,模拟三个线程,看输出结果:

package com.cljtest.demo.mylock;

public class ReentrantReadWriteLockDemo {
    private int i = 0;
    private int j = 0;

    public void out(){
        System.out.println(Thread.currentThread().getName()+"i的值为----->"+i+"--j的值为----->"+j);
    }

    public void inCreate(){
        i++;
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        j++;
    }

    public static void main(String[] args) {
        ReentrantReadWriteLockDemo readWriteLockDemo = new ReentrantReadWriteLockDemo();
        for(int i = 0;i<3;i++) {
            new Thread(() -> {
                readWriteLockDemo.inCreate();
                readWriteLockDemo.out();
            }).start();
        }
    }
}

运行结果为:
在这里插入图片描述
中间模拟了时间较长的操作,进行了sleep的休眠操作,运行结果发现,j的值不是我们想要的,首先进入increate方法,(可以将这个方法看成写的方法)先将i进行了变量增加的操作,然后执行了休眠,可能休眠还没结束,就已经开始了读的out()的方法,这个时候j的值还没有变化,所以才会造成i和j不是同步递增的结果。

可以考虑out()读的方法上加synchronized锁起来,也将写的increate()方法加上这个锁,这样就可以同步了,但是比较浪费资源,而且需要等待。这时就可以用读写锁ReadWriteLock进行操作:

private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

Lock readLock = readWriteLock.readLock();
Lock writeLock = readWriteLock.writeLock();

用readLock.lock()在读的方法out()上加上锁,最后一定要注意写上finally进行锁的释放。
用writeLock.lock()对写的increate()方法加锁,同样最后要进行释放。

public void out(){
    readLock.lock();
    try {
        System.out.println(Thread.currentThread().getName()+"i的值为----->"+i+"--j的值为----->"+j);
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        //一定要注意手动释放锁
        readLock.unlock();
    }
}
public void inCreate(){
    writeLock.lock();
    try {
        i++;
        Thread.sleep(1000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }finally {
        writeLock.unlock();
    }
    j++;
}

运行,结果如下:

在这里插入图片描述
这样就达到了想要的i和j的值一致的结果了。

接下来来证明读写锁的特性:
1、写写互斥,模拟两个线程进行写的操作,debug验证:

   new Thread(()->{
       readWriteLockDemo.inCreate();
   },"写线程1").start();

   new Thread(()->{
       readWriteLockDemo.inCreate();
   },"写线程2").start();
}

主方法模拟两个写线程
在这里插入图片描述
debug走到还未释放锁的时候,切换写线程2
在这里插入图片描述
线程2尝试获取锁的时候进入了等待状态,这就证明了读写锁的写写互斥。

下面验证读写互斥:

new Thread(()->{
    readWriteLockDemo.out();
},"读线程").start();

new Thread(()->{
    readWriteLockDemo.inCreate();
},"写线程").start();

写线程先运行

读线程处于等待状态
在这里插入图片描述
证明读写互斥。

下面证明读读之间的共享:
在这里插入图片描述

在这里插入图片描述
读线程2是可以正常运行拿到锁的,所以读写锁中读读是可以共享的。
以上三个debug的模拟调试,证明了读写锁的特性:写写互斥、读写互斥和读读共享。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!