Java并发编程 - 显示锁Lock和ReentrantLock
2019独角兽企业重金招聘Python工程师标准>>>
Lock
Lock是一个接口,提供了无条件的、可轮询的、定时的、可中断的锁获取操作,所有加锁和解锁的方法都是显式的。包路径是:java.util.concurrent.locks.Lock
。核心方法有 lock()
,unlock()
,tryLock()
,实现类有 ReentrantLock
、ReentrantReadWriteLock.ReadLock
、ReentrantReadWriteLock.WriteLock
。
** 方法及说明 **
public abstract interface Lock {// 获取锁。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,// 该线程将一直处于休眠状态void lock();// 如果当前线程未被中断,则获取锁。如果锁可用,则获取锁,并立即返回。// 如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态:// 锁由当前线程获得;或者其他某个线程中断当前线程,并且支持对锁获取的中断。// 如果当前线程:在进入此方法时已经设置了该线程的中断状态;// 或者在获取锁时被中断,并且支持对锁获取的中断,则将抛出`InterruptedException`,并清除当前线程的已中断状态void lockInterruptibly() throws InterruptedException;// 仅在调用时锁为空闲状态才获取该锁。如果锁可用,则获取锁,并立即返回值 true。// 如果锁不可用,则此方法将立即返回值 false。通常对于那些不是必须获取锁的操作可能有用boolean tryLock();// 如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。// 如果锁可用,则此方法将立即返回值 true。如果锁不可用,出于线程调度目的,// 将禁用当前线程,并且在发生以下三种情况之一前,该线程将一直处于休眠状态boolean tryLock(long time, TimeUnit unit) throws InterruptedException;// 释放锁。对应于 lock()、tryLock()、tryLock(time, unit)、lockInterruptibly() 等操作,// 如果成功的话应该对应着一个`unlock()`,这样可以避免死锁或者资源浪费void unlock();// 返回用来与此 Lock 实例一起使用的 Condition 实例Condition newCondition();
}
ReentrantLock
ReentrantLock是Lock的实现类,是一个互斥的同步器,它具有扩展的能力。在竞争条件下,ReentrantLock 的实现要比现在的 synchronized 实现更具有可伸缩性。(有可能在 JVM 的将来版本中改进 synchronized 的竞争性能)这意味着当许多线程都竞争相同锁定时,使用 ReentrantLock 的吞吐量通常要比 synchronized 好。换句话说,当许多线程试图访问 ReentrantLock 保护的共享资源时,JVM 将花费较少的时间来调度线程,而用更多个时间执行线程。虽然 ReentrantLock 类有许多优点,但是与同步相比,它有一个主要缺点 — 它可能忘记释放锁定。ReentrantLock是在工作中对方法块加锁使用频率最高的。
** 使用方法如下: **
class X {private final ReentrantLock lock = new ReentrantLock();// …public void m() {lock.lock(); // 获得锁try {// … 方法体} finally {lock.unlock();//解锁}}
}
** Lock与synchronized 的比较: **
- Lock使用起来比较灵活,但是必须有释放锁的动作;
- Lock必须手动释放和开启锁,synchronized 不需要;
- Lock只适用与代码块锁,而synchronized 对象之间的互斥关系;
示例
请注意以下两种方式的区别:
第一种方式:两个方法之间的锁是独立的
public class ReentrantLockDemo {public static void main(String[] args) {final Count ct = new Count();for (int i = 0; i < 2; i++) {new Thread() {public void run() {ct.get();}}.start();}for (int i = 0; i < 2; i++) {new Thread() {public void run() {ct.put();}}.start();}}
}class Count {public void get() {final ReentrantLock lock = new ReentrantLock();try {lock.lock(); // 加锁System.out.println(Thread.currentThread().getName() + " get begin");Thread.sleep(1000);// 模仿干活System.out.println(Thread.currentThread().getName() + " get end");lock.unlock(); // 解锁} catch (InterruptedException e) {e.printStackTrace();}}public void put() {final ReentrantLock lock = new ReentrantLock();try {lock.lock(); // 加锁System.out.println(Thread.currentThread().getName() + " put begin");Thread.sleep(1000);// 模仿干活System.out.println(Thread.currentThread().getName() + " put end");lock.unlock(); // 解锁} catch (InterruptedException e) {e.printStackTrace();}}
}
运行结果如下(每次运行结果都是不一样的,仔细体会一下):
Thread-0 get begin
Thread-1 get begin
Thread-2 put begin
Thread-3 put begin
Thread-0 get end
Thread-2 put end
Thread-3 put end
Thread-1 get end
第二种方式,两个方法之间使用相同的锁
ReentrantLockDemo 类的内容不变,将Count中的ReentrantLock改成全局变量,如下所示:
class Count {final ReentrantLock lock = new ReentrantLock();public void get() {try {lock.lock(); // 加锁System.out.println(Thread.currentThread().getName() + " get begin");Thread.sleep(1000);// 模仿干活System.out.println(Thread.currentThread().getName() + " get end");lock.unlock(); // 解锁} catch (InterruptedException e) {e.printStackTrace();}}public void put() {try {lock.lock(); // 加锁System.out.println(Thread.currentThread().getName() + " put begin");Thread.sleep(1000);// 模仿干活System.out.println(Thread.currentThread().getName() + " put end");lock.unlock(); // 解锁} catch (InterruptedException e) {e.printStackTrace();}}
}
运行结果如下(每次运行结果一样的,仔细体会一下):
Thread-0 get begin
Thread-0 get end
Thread-1 get begin
Thread-1 get end
Thread-2 put begin
Thread-2 put end
Thread-3 put begin
Thread-3 put end
转载于:https://my.oschina.net/u/215547/blog/809379
Java并发编程 - 显示锁Lock和ReentrantLock相关推荐
- Java并发编程-无锁CAS与Unsafe类及其并发包Atomic
[版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/72772470 出自[zejian ...
- Java并发编程之锁机制之LockSupport工具
关于文章涉及到的jdk源码,这里把最新的jdk源码分享给大家----->jdk源码 前言 在上篇文章<Java并发编程之锁机制之AQS(AbstractQueuedSynchronizer ...
- Java并发编程(06):Lock机制下API用法详解
本文源码:GitHub·点这里 || GitEE·点这里 一.Lock体系结构 1.基础接口简介 Lock加锁相关结构中涉及两个使用广泛的基础API:ReentrantLock类和Condition接 ...
- 6. Java并发编程-并发包-Lock和Condition
前文介绍了java语言本身通过synchronized, wait, notify实现了管程,解决了并发编程两大难题:互斥和同步. 这两大问题并发包中也得到了相应的实现,分别时Lock和Conditi ...
- java并发锁有哪些,Java并发编程-公平锁与非公平锁
写这个文章的时候让我想起了让子弹飞的一个台词 公平,公平,还是tmd公平! 什么是公平和非公平 首先,我们来看下什么是公平锁和非公平锁. 公平锁指的是按照线程请求的顺序,来分配锁: 非公平锁指的是不完 ...
- Java 并发编程—有锁互斥机制及AQS理论
原文作者:Java并发编程 原文地址:AQS这样学就很简单了 目录 一.有锁互斥机制 二.AQS如何实现互斥 三.结语 如果你是道格李,你要实现一套机制来保证线程互斥,你会如何实现呢?你肯定不会一上来 ...
- Java并发编程—JUC的Lock锁
一.Lock (JUC锁) JUC 锁位于java.util.concurrent.locks包下,为锁和等待条件提供一个框架,它不同于内置同步和监视器. CountDownLatch,CyclicB ...
- 【java】java 并发编程 StampedLock 锁 【不重要】
文章目录 1.概述 2.synchronized 3.读写锁 3.1 读写锁缺点 4.StampedLock 4.1 缺点 5.案例 5.1 案例1 5.1 案例2 6.性能对比 7.总结 1.概述 ...
- Java并发编程—无锁互斥机制及CAS原理
目录 一.CAS简介 二.AtomicInteger代码演示 三.CAS 实现 四.弊端 一.CAS简介 在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令 ...
最新文章
- Java项目:在线商城系统(前后端分离+java+vue+Springboot+ssm+mysql+maven+redis)
- 1.4 正则化-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
- 触摸屏通常接在微型计算机,计算机应用基础习题答案.doc
- Autowire异常
- vs 2008 Ide 设置
- ref和out的联系及区别(转)
- 第八节:ES6为数组做了哪些扩展?
- JS弹出可拖动层,并蒙住页面
- hdu 2604 Queuing AC自动机构造递推式-矩阵-结果
- RHEL6 kernel bug在hadoop上的测试
- Flash CS3无法导出测试影片问题解决
- 一人饮酒醉用计算机版,玩家自制游戏版《一人饮酒醉》,歪唱喊麦笑翻全场
- 特斯拉是如何训练自动驾驶的?
- Shaderlab 玻璃效果
- 用EXCEL宏编写坐标转换
- Memcached Redis构建缓存服务器
- 西安市2012年教师资格证考试报名时间:3月10-15日
- Linux各发行版的前世今生
- 蓝桥杯嵌入式(一)学习准备
- java导出excel
热门文章
- TensorFlow函数(十)tf.global_variables_initializer()
- 微信生态圈盈利模式分析
- background-position 用法介绍
- 删除eclipse或者MyEclipse的workspace记录
- Python使用BeautifulSoup爬取网页中主体部分的内容,并导出为pdf格式
- IDEA查看Java类的UML关系图
- kotlin中mainactivity无法直接调用xml中的控件_使用Kotlin高效地开发Android App(一)
- 微服务模块综合管理(模块视图管理,自动化热部署,前端资源实时刷新......)
- seata不兼容mysql8的解决方案
- ORACLE不完全恢复的几种情况