博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【并发编程】ReentrantLock使用介绍
阅读量:4080 次
发布时间:2019-05-25

本文共 4163 字,大约阅读时间需要 13 分钟。

Java 5.0之前,在协调对共享对象的访问时可以使用的机制只有synchronized和volatile。java 5.0增加了一种新的机制:ReentrantLock,用以当内置枷锁机制不适用时,作为一种可选择的高级功能。

       Lock提供了一种无条件的、可轮询的、定时的以及可中断的锁获取操作,下面来看Lock接口提供了哪些方法:

public interface Lock {
void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); Condition newCondition();}

下面来看一些ReentrantLock的用法:

一.通过轮询避免死锁

    关于死锁此处就不再赘述了,楼主之前写过一篇死锁的文章,有兴趣的可以移步:

下面直接看用ReentrantLoc的实现:

先构造一个对象类:

public class PersonVO {
/** 年龄 */ private int age; /** ReentrantLock锁 */ private Lock lock = new ReentrantLock(); public int getAge() { return age; } public Lock getLock() { return lock; }}

下面看测试方法:

@Testpublic void loopLock() throws InterruptedException {    PersonVO qian = new PersonVO();    PersonVO zhang = new PersonVO();    Thread thread1 = new Thread(() -> {        while (true) {            if (qian.getLock().tryLock()) {                try {                    System.out.println("【thread1】获取到钱先生的锁");                    Thread.sleep(200L);                    if (zhang.getLock().tryLock()) {                        try {                            System.out.println("【thread1】获取到张先生的锁");                        } finally {                            zhang.getLock().unlock();                        }                    }                } catch (InterruptedException e) {                    e.printStackTrace();                } finally {                    qian.getLock().unlock();                }            }        }    });    Thread thread2 = new Thread(() -> {        while (true) {            if (zhang.getLock().tryLock()) {                try {                    System.out.println("【thread2】获取到张先生的锁");                    Thread.sleep(33L);                    if (qian.getLock().tryLock()) {                        try {                            System.out.println("【thread2】获取到钱先生的锁");                        } finally {                            qian.getLock().unlock();                        }                    }                } catch (InterruptedException e) {                    e.printStackTrace();                } finally {                    zhang.getLock().unlock();                }            }        }    });    thread1.start();    thread2.start();    Thread.sleep(100L);}

输出结果:

【thread1】获取到钱先生的锁【thread2】获取到张先生的锁【thread2】获取到张先生的锁【thread2】获取到张先生的锁

可以看到,并没有出现死锁,如果此处用synchronized关键字来做对象锁的话,两个线程获取的锁顺序不一致是会造成死锁的。(这里代码最后一行只是为了避免主线程执行完毕两个子线程会直接终止)

二.指定尝试时间锁,防止一直阻塞

    还是用上例的PersonVO对象,下面直接看测试代码:

public void lockWithTime() throws InterruptedException {    PersonVO zhang = new PersonVO();    Thread thread1 = new Thread(() -> {       zhang.getLock().lock();        try {            System.out.println("【thread1】获取到张先生的锁");            Thread.sleep(200L);        } catch (InterruptedException e) {            e.printStackTrace();        }finally {            zhang.getLock().unlock();        }    });    Thread thread2 = new Thread(() -> {        try {            if (zhang.getLock().tryLock(100L, TimeUnit.MILLISECONDS)) {                try {                    System.out.println("【thread2】获取到张先生的锁");                } finally {                    zhang.getLock().unlock();                }            } else {                System.out.println("【thread2】未能获取到张先生的锁");            }        } catch (InterruptedException e) {            e.printStackTrace();        }    });    thread1.start();    thread2.start();    Thread.sleep(300L);}

运行看结果:

【thread1】获取到张先生的锁【thread2】未能获取到张先生的锁

通过运行结果可看到,线程2并没有获取到锁,在指定时间未获取到锁后继续跑完其余流程,并未造成线程阻塞。

三.可中断锁

    lockInterruptibly方法能在阻塞等待获取锁的同时保持对中断的响应,所以可以通过其他线程中断锁,并由当前线程执行中断处理,看如下代码:

@Testpublic void lockInterruptiblyTest() throws Exception {    final Lock lock = new ReentrantLock();    lock.lock();    Thread t1 = new Thread(() -> {        try {            lock.lockInterruptibly();            System.out.println("获取到锁");        } catch (InterruptedException e) {            System.out.println("执行中断处理.");        }    });    t1.start();    Thread.sleep(100L);    t1.interrupt();    Thread.sleep(1000L);}

运行看结果:

执行中断处理.

欢迎关注个人博客:

转载地址:http://mesni.baihongyu.com/

你可能感兴趣的文章
我觉得嵌入式面试三要素:基础吃透+项目+大量刷题,缺一不可。不刷题是不行的。而且得是大量刷,刷出感觉套路,别人做题都做得是固定题型套路条件反射了,你还在那慢慢理解慢慢推是不行的,也是考研的教训。
查看>>
嵌入式面试题错题集(我自己做的)
查看>>
ACfly飞控用STlink下载的接口,接线,并用STlink(SWD)下载程序
查看>>
死锁的四个必要条件
查看>>
我有个设想既然T265是全局定位,我能不能直接给定一个轨迹函数(可以是比较复杂曲线),然后它按照这种路线去飞行。
查看>>
嵌入式-操作系统方面常见的面试题
查看>>
7000字干货 | 嵌入式必备技能之Git的使用
查看>>
git我到现在也没学会,可能我更喜欢视频教程,不喜欢文字教程,看到那一堆关系就乱了。
查看>>
我现在发觉github真的是一个好东西,可以保存你每次对工程的修改,不用再像以前一样每个版本的工程都单独保存到一个文件夹。。。
查看>>
我还是想真正做出摄像头+VINS的无人机定点飞
查看>>
Ubuntu16.04+RealsenseT265跑通VINS-Fusion
查看>>
小觅这里有直接教你怎么整合它的SDK和vins一起运行的,搞不好用小觅更快点?
查看>>
使用小觅相机标准入门版运行vins
查看>>
干货 | 一起快速上手 VINS-Fusion
查看>>
我的联想手机出问题了
查看>>
这里再次说了TX2的CPU比较弱
查看>>
视觉SLAM方案整理及摄像头选型调研(他首推ZED)
查看>>
B站上的github视频教程笔记(包含两个B站视频,我觉得看这两个B站视频,github从原理到操作都可以会了)
查看>>
关于git存储空间的注意
查看>>
将一个既有的Keil工程加入git管理的方法
查看>>