前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ReentrantLock会!ReentrantReadWriteLock呢?不懂快戳进来看看

ReentrantLock会!ReentrantReadWriteLock呢?不懂快戳进来看看

作者头像
良月柒
发布2019-03-20 15:42:42
8040
发布2019-03-20 15:42:42
举报

技术文章第一时间送达!

这两天在加深多线程的相关知识,刚好遇到了ReentrantLock和ReentrantReadWriteLock这两个类,觉得后者的一些特性对多线程的性能还是提升很大的,挺有意思,特此分享一下,非常简单的哦。

进入正题,首先,先来介绍一下今天的主角之一:ReentrantLock

我们都知道在Java多线程中,可以使用synchronized关键字来实现线程之间同

步互斥。

但在JDK1.5中新增加了ReentrantLock类也能达到同样的效果,并且在扩展功能上也更加强大,比如具有嗅探锁定、多路分支通知等功能,而且在使用上也比synchronized更加的灵活。

由来和作用,相信你已经知道了,纸上谈兵可能理解不深切,接下来亲身体验一下它的用法。(如了解可跳过这里,照顾一下基础薄弱的小伙伴)

ReentLock的简单用法:

创建Myservice类

创建一个线程A

创建一个线程B

启动类:

运行结果如下:

我们可以看到,线程A获取到锁的时间和线程B获取到锁的时间,是相差了5秒,在代码中,我们通过Thread.sleep(5000)使线程睡眠了5秒,证明,同一时刻只能有一个线程获取到锁,达到互斥的目的。

类ReentrantLock具有完全互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务。

但是呢?有没有发现一个问题。虽然ReentrantLock这样做虽然保证了实例变量的线程安全性,但效率确实非常低下的。

有没有好的方法呢?

这个时候,就是今天的另外一个主角登场的时候了:ReentrantReadWriteLock

针对上面问题在JDK中体用了另一种读写锁ReentrantReadWriteLock类,使用它可以加快运行效率,在某些不需要操作实例变量的方法中,完全可以使用读写锁ReentrantReadWriteLock来提升该方法的代码运行速度。

先来看看它的用法

创建一个Service类

创建一个线程A

代码语言:javascript
复制
/**
 * 作者:LKP
 * 时间:2018/11/27
 */
public class ThreadA extends Thread{

    private Service service;
    public ThreadA(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        service.read();
    }
}

创建一个线程B

代码语言:javascript
复制
/**
 * 作者:LKP
 * 时间:2018/11/27
 */
public class ThreadB extends Thread {

    private Service service;

    public ThreadB(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        service.read();
    }
}

启动类:

代码语言:javascript
复制
/**
 * 作者:LKP
 * 时间:2018/11/27
 */
public class Run {

    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        ThreadB b = new ThreadB(service);
        a.setName("A");
        b.setName("B");
        a.start();
        b.start();
    }

}

来看一下运行结果:

时间是一样的,为什么呢?难道是锁没起作用,哈哈哈,这就是它的一个特性,读读共享。简单来说,就是如果多个线程,都是进行读取操作,那么他们是可以同时获取到锁的。

再继续看看,修改Service类

其他的类不作修改,然后运行

你发现了什么?时间不一致,证明,同一时间只有一个线程获取到锁了,它们是互斥的,这就是另外一个特性:写写互斥。简单来说就是,当有多个线程进行写操作的时候,那么同时只有一个线程能获取到锁。

再继续往下看看

修改Service类

修改一下线程A类

代码语言:javascript
复制
/**
 * 作者:LKP
 * 时间:2018/11/27
 */
public class ThreadA extends Thread{

    private Service service;
    public ThreadA(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        service.read();
    }
}

修改一下线程B类

代码语言:javascript
复制
/**
 * 作者:LKP
 * 时间:2018/11/27
 */
public class ThreadB extends Thread {

    private Service service;
    public ThreadB(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        service.wirte();
    }
}

启动类可以不用修改的啦

代码语言:javascript
复制
/**
 * 作者:LKP
 * 时间:2018/11/27
 */
public class Run {

    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
    }

}

运行结果

时间是不一样的,证明它们是互斥运行的,你想到了什么呢?没错,就是读写互斥。就是,当多个线程进入锁的时候,如果一个线程获取的是读锁,一个线程获取的是写锁,那么它们也是互斥的。

那如果先获取写锁,后获取读锁呢?

来试试

修改启动类

代码语言:javascript
复制
/**
 * 作者:LKP
 * 时间:2018/11/27
 */
public class Run {

    public static void main(String[] args) {
        Service service = new Service();
        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();
    }

}

再来看看运行结果

证明先获取写锁,在获取读锁,它们是一样的,都是互斥进行的。

总结

读写锁表示也有两个锁,一个是读操作下相关的锁,也称为共享锁;另一个是写操作相关的锁,也叫排他锁。

也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。

在没有线程Thread进行写入操作时,进行读取操作的多个Thread都可以获取读锁,而进行写入操作的Thread只有在获取写锁后才能进行写入操作。

即多个Thread可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作。

今天的文章就到这里了,有什么错误之处,欢迎号内留言

如果文章觉得不错,可以号内送朵:

你的支持,是我最大的动力

感谢阅读!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的成长之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档