【并发编程】ReentrantLock使用介绍
来源:互联网 发布:魔兽副本数据库 编辑:程序博客网 时间:2024/04/30 08:15
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的用法:
一.通过轮询避免死锁
关于死锁此处就不再赘述了,楼主之前写过一篇死锁的文章,有兴趣的可以移步:
http://blog.scarlettbai.com/sync-t1459676182/
下面直接看用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://blog.scarlettbai.com
0 0
- 【并发编程】ReentrantLock使用介绍
- 并发编程--互斥锁ReentrantLock
- Java并发编程 之 Condition与ReentrantLock的使用
- 并发编程实践五:ReentrantLock
- 并发编程实践五:ReentrantLock
- Java并发编程(三)--ReentrantLock
- JAVA并发编程学习笔记之ReentrantLock
- JAVA并发编程学习笔记之ReentrantLock
- JAVA并发编程--Semaphore、CountDownLatch、ReentrantLock、CyclicBarrier
- 深入学习java并发编程:ReentrantLock
- java 并发编程学习之三 ---- ReentrantLock
- java并发编程——ReentrantLock源码
- Java并发编程之ReentrantLock源码解析
- java并发编程学习7--同步--ReentrantLock
- ReentrantLock和ReentrantReadWriteLock使用介绍
- Java 并发编程中使用 ReentrantLock 替代 synchronized 关键字原语
- 并发编程学习总结(五) :java 显式锁ReentrantLock使用详解之条件对象(2)
- 并发编程学习总结(六) :java 显式锁ReentrantLock使用详解之测试锁与超时
- hadoop配置步骤
- 正则表达式
- [Pascal][简单题]兔子繁殖问题
- javaScript实现复制功能
- php学习笔记-echo和print语句区别
- 【并发编程】ReentrantLock使用介绍
- 计算结构体的字节数
- 基于注解的对象关系映射的实现(一):使用示例
- Eclipse创建java web工程
- Thymeleaf设置任意属性
- HBase学习笔记——系统架构
- 验证同步函数(静态与非静态)的锁是否是Object
- 当出现no changes added to commit时如何正确使用git提交命令
- SQL SERVER 转换大小写