java多线程系列(四)—ReentrantLock的使用

java多线程系列(四)—ReentrantLock的使用

Lock的使用

前言:本系列将从零开始讲解java多线程相关的技术,内容参考于《java多线程核心技术》与《java并发编程实战》等相关资料,希望站在巨人的肩膀上,再通过我的理解能让知识更加简单易懂。

目录

ReentrantLocak特性(对比synchronized)

  • 尝试获得锁
  • 获取到锁的线程能够响应中断

ReentrantLock(重入锁)

public class MyService { private Lock lock = new ReentrantLock(); public void testMethod() { lock.lock(); for (int i = 0; i < 5; i++) { System.out.println("ThreadName=" + Thread.currentThread().getName() + (" " + (i + 1))); } lock.unlock(); } }

效果和synchronized一样,都可以同步执行,lock方法获得锁,unlock方法释放锁

await方法

public class MyService { private Lock lock = new ReentrantLock(); private Condition condition=lock.newCondition(); public void testMethod() { try { lock.lock(); System.out.println("开始wait"); condition.await(); for (int i = 0; i < 5; i++) { System.out.println("ThreadName=" + Thread.currentThread().getName() + (" " + (i + 1))); } } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } finally { lock.unlock(); } } }
  • 通过创建Condition对象来使线程wait,必须先执行lock.lock方法获得锁

signal方法

public void signal() { try { lock.lock(); condition.signal(); } finally { lock.unlock(); } }
  • condition对象的signal方法可以唤醒wait线程

创建多个condition对象

  • 一个condition对象的signal(signalAll)方法和该对象的await方法是一一对应的,也就是一个condition对象的signal(signalAll)方法不能唤醒其他condition对象的await方法
  • ReentrantLock类可以唤醒指定条件的线程,而object的唤醒是随机的

Condition类和Object类

  • Condition类的awiat方法和Object类的wait方法等效
  • Condition类的signal方法和Object类的notify方法等效
  • Condition类的signalAll方法和Object类的notifyAll方法等效

Lock的公平锁和非公平锁

Lock lock=new ReentrantLock(true);//公平锁 Lock lock=new ReentrantLock(false);//非公平锁 
  • 公平锁指的是线程获取锁的顺序是按照加锁顺序来的,而非公平锁指的是抢锁机制,先lock的线程不一定先获得锁。

ReentrantLock类的方法

  • getHoldCount() 查询当前线程保持此锁的次数,也就是执行此线程执行lock方法的次数
  • getQueueLength()返回正等待获取此锁的线程估计数,比如启动10个线程,1个线程获得锁,此时返回的是9
  • getWaitQueueLength(Condition condition)返回等待与此锁相关的给定条件的线程估计数。比如10个线程,用同一个condition对象,并且此时这10个线程都执行了condition对象的await方法,那么此时执行此方法返回10
  • hasWaiters(Condition condition)查询是否有线程等待与此锁有关的给定条件(condition),对于指定contidion对象,有多少线程执行了condition.await方法
  • hasQueuedThread(Thread thread)查询给定线程是否等待获取此锁
  • hasQueuedThreads()是否有线程等待此锁
  • isFair()该锁是否公平锁
  • isHeldByCurrentThread() 当前线程是否保持锁锁定,线程的执行lock方法的前后分别是false和true
  • isLock()此锁是否有任意线程占用
  • lockInterruptibly()如果当前线程未被中断,获取锁
  • tryLock()尝试获得锁,仅在调用时锁未被线程占用,获得锁
  • tryLock(long timeout TimeUnit unit)如果锁在给定等待时间内没有被另一个线程保持,则获取该锁

tryLock和lock和lockInterruptibly的区别

  • tryLock能获得锁就返回true,不能就立即返回false,tryLock(long timeout,TimeUnit unit),可以增加时间限制,如果超过该时间段还没获得锁,返回false
  • lock能获得锁就返回true,不能的话一直等待获得锁
  • lock和lockInterruptibly,如果两个线程分别执行这两个方法,但此时中断这两个线程,前者不会抛出异常,而后者会抛出异常

读写锁

  • ReentrantLock是完全互斥排他的,这样其实效率是不高的。
public void read() { try { try { lock.readLock().lock(); System.out.println("获得读锁" + Thread.currentThread().getName() + " " + System.currentTimeMillis()); Thread.sleep(10000); } finally { lock.readLock().unlock(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
  • 读锁,此时多个线程可以或得读锁
public void write() { try { try { lock.writeLock().lock(); System.out.println("获得写锁" + Thread.currentThread().getName() + " " + System.currentTimeMillis()); Thread.sleep(10000); } finally { lock.writeLock().unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } }
  • 写锁,此时只有一个线程能获得写锁
public void read() { try { try { lock.readLock().lock(); System.out.println("获得读锁" + Thread.currentThread().getName() + " " + System.currentTimeMillis()); Thread.sleep(10000); } finally { lock.readLock().unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } } public void write() { try { try { lock.writeLock().lock(); System.out.println("获得写锁" + Thread.currentThread().getName() + " " + System.currentTimeMillis()); Thread.sleep(10000); } finally { lock.writeLock().unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } }
  • 结果是读锁释放后才执行写锁的方法,说明读锁和写锁是互斥的

总结

  • Lock类也可以实现线程同步,而Lock获得锁需要执行lock方法,释放锁需要执行unLock方法
  • Lock类可以创建Condition对象,Condition对象用来是线程等待和唤醒线程,需要注意的是Condition对象的唤醒的是用同一个Condition执行await方法的线程,所以也就可以实现唤醒指定类的线程
  • Lock类分公平锁和不公平锁,公平锁是按照加锁顺序来的,非公平锁是不按顺序的,也就是说先执行lock方法的锁不一定先获得锁
  • Lock类有读锁和写锁,读读共享,写写互斥,读写互斥

我觉得分享是一种精神,分享是我的乐趣所在,不是说我觉得我讲得一定是对的,我讲得可能很多是不对的,但是我希望我讲的东西是我人生的体验和思考,是给很多人反思,也许给你一秒钟、半秒钟,哪怕说一句话有点道理,引发自己内心的感触,这就是我最大的价值。(这是我喜欢的一句话,也是我写博客的初衷)

作者:jiajun 出处: http://www.cnblogs.com/-new/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。

https://blog.csdn.net/Evankaka/article/details/44153709

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101331.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • Flask—jsonify方式(api接口)「建议收藏」

    Flask—jsonify方式(api接口)「建议收藏」GET方法post方法PUT方法DELETE方法GET方法fromflaskimportFlask,jsonify,abort,make_responseapp=Flask(__name__)articles=[{‘id’:1,’title’:’thewaytopyt…

    2022年5月10日
  • MySQL 常用语句_数据库基本语句大全

    MySQL 常用语句_数据库基本语句大全在cmd中启用MySQL:mysql-uroot-p******1、新建用户:    >CREATEUSERnameIDENTIFIEDBY’ssapdrow’;  2、更改密码:    >SETPASSWORDFORname=PASSWORD(‘fdddfd’);  3、权限管理    >SHOWGRANTSFORname;//查看name用户权限    >GRANTSELECTONdb_name.*TO.

    2022年9月5日
  • 硬件资料和软件资料_电脑硬件检测工具哪个好

    硬件资料和软件资料_电脑硬件检测工具哪个好一些常用的资料_硬件/系统/等标题前数字代表专题所在楼层数2. BIOS报警声意义3. BIOS自检与开机故障相关问题5. 计算机几个常见指标的意义6. 显卡GPU参数7. 显示卡常见故障全面解决8. 集成声卡常见故障及解决9. 显示器经典故障以及处理办法10. AMI主板代码大全(BIOS-ID)12. AWARD主板代码大全(BIOS-ID)16. 黑屏故障17. WindowsX

    2022年10月20日
  • 安装Esxi系统&重装Esxi系统

    安装Esxi系统&重装Esxi系统安装esxi系统、或者已经安装了esxi需要重装环境:DellR730服务器。前期准备:将VMwareESXi5.5.0的安装镜像要提前准备好,通过光碟、U盘、idrac管理界面挂载方式安装都行。1、加载VMwareESXi5.5.0版的ISO文件,ESXi引导装入程序,并且开始安装。按enter键,进入安装界面。如图所示:2、在安装ESXi引导加载的过程,这个要等一下,在窗口上可…

    2022年6月25日
  • python读取图片名称_照片文件名怎么改jpg

    python读取图片名称_照片文件名怎么改jpgPython读取文件夹下的.jpg图片,提取图片的文件名。最近做的图像处理,需要读取文件夹下所有图片和对应的文件名,进行相关处理,最后保存的图片要求文件的名称与原图名称一致。百度找了好多例子也没找到,最后零零碎碎的搜索,通过一些个人的思考把相关的知识点和程序结合,总算做出来了。举个简单的功能:读取文件夹下的图片和对应的图片名,先处理成灰度图像,再进行保存,要求保存的图片的名称与原图名称一致。效果如下:读取F:\image下的000~004.jpg,最后处理的灰度图片保存在F:\image\sa

    2022年9月3日
  • 此工作站和主域直接信任失败_此域与工作站信任失效

    此工作站和主域直接信任失败_此域与工作站信任失效当您登录到域环境中运行Windows7的计算机上时,您会收到以下错误消息:此工作站和主域之间的信任关系失败。解决方案若要解决此问题,请从域中删除计算机,然后将计算机连接到域。若要执行此操作,请执行以下步骤:使用本地管理员帐户登录到计算机上。单击开始,右键单击计算机,然后单击属性。单击计算机名称旁边的更改设置。在计算机名选项卡上,单击更改。在

    2022年10月18日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号