reentrantlock_lock condition

reentrantlock_lock conditionReentrantLock锁的底层实现已经阐述过了,那么如何使用,本文进行下样例展示,主要说两个功能:1.lock及中断,2.申请等待时间;lock锁/***@Description:*@author:Erick*@version:1.0*@time:2018-9-25*/publicclassReentrantLockThreadimple…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

ReentrantLock锁的底层实现已经阐述过了,那么如何使用,本文进行下样例展示,主要说3个:1. lock及中断,2. 申请等待时间,3、公平锁

lock锁

/** * @Description : * @author : Erick * @version : 1.0 * @time :2018-9-25 */ public class ReentrantLockThread implements Runnable{ 
     private static ReentrantLock reentrantLock = new ReentrantLock(); private int i = 0; public void run() { 
     for (int j = 0; j < 10; j++) { 
     //上锁 reentrantLock.lock(); try { 
     i++; System.out.println("当前线程"+Thread.currentThread().getName()+"输出 i :" + i); } finally { 
     //释放锁 reentrantLock.unlock(); } } } } 

上例中一个实现一个线程,并定义ReentrantLock,与synchronized不同的是要显示的lock上锁并手动释放锁,是一套缺一不可,将上锁和释放锁注释然后调用会出现线程交替执行的情况,我们写个测试类

/** * @Description : * @author : Erick * @version : 1.0 * @time :2018-9-25 */ public class ReentrantLockTest { 
     public static void main(String[] args) { 
     //定义两个线程 ReentrantLockThread reentrantLockThread1 = new ReentrantLockThread(); ReentrantLockThread reentrantLockThread2 = new ReentrantLockThread(); //调用run方法执行其实就是调用的接口方法,主线程运行在打印线程名称时都是main, //而使用Thread.start()则是新起一个线程进行调用,更新执行标识 // reentrantLockThread1.run(); // reentrantLockThread2.run(); Thread thread1 = new Thread(reentrantLockThread1); Thread thread2 = new Thread(reentrantLockThread2); thread1.start(); thread2.start(); } } 

为方便展示只循环了10次注释掉上锁和释放锁的代码,执行结果为:

当前线程Thread-0输出 i :1 当前线程Thread-1输出 i :1 当前线程Thread-0输出 i :2 当前线程Thread-1输出 i :2 当前线程Thread-0输出 i :3 当前线程Thread-1输出 i :3 当前线程Thread-0输出 i :4 当前线程Thread-1输出 i :4 当前线程Thread-0输出 i :5 当前线程Thread-1输出 i :5 当前线程Thread-0输出 i :6 当前线程Thread-1输出 i :6 当前线程Thread-0输出 i :7 当前线程Thread-1输出 i :7 当前线程Thread-0输出 i :8 当前线程Thread-1输出 i :8 当前线程Thread-1输出 i :9 当前线程Thread-0输出 i :9 当前线程Thread-1输出 i :10 当前线程Thread-0输出 i :10 

若加上锁,则是一个先执行完另外一个再执行,获取到锁后,第二个线程在请求时发现锁被占用则加入到队列中等待,所以等第一个线程执行完成后,第二个线程才会执行,执行结果如下:

当前线程Thread-0输出 i :1 当前线程Thread-0输出 i :2 当前线程Thread-0输出 i :3 当前线程Thread-0输出 i :4 当前线程Thread-0输出 i :5 当前线程Thread-0输出 i :6 当前线程Thread-0输出 i :7 当前线程Thread-0输出 i :8 当前线程Thread-0输出 i :9 当前线程Thread-0输出 i :10 当前线程Thread-1输出 i :1 当前线程Thread-1输出 i :2 当前线程Thread-1输出 i :3 当前线程Thread-1输出 i :4 当前线程Thread-1输出 i :5 当前线程Thread-1输出 i :6 当前线程Thread-1输出 i :7 当前线程Thread-1输出 i :8 当前线程Thread-1输出 i :9 当前线程Thread-1输出 i :10 

中断

中断是两个线程分表获取对方需要的数据时即死锁,为了防止线程一直等待浪费资源,ReentrantLock提供了中断响应接口支持,及可以手动调用线程中断来强制让一个线程中断并返回异常信息,而另外一个线程则会拿到锁继续执行。

/** * @Description :中断响应 * @author : Erick * @time :2018-9-25 */ public class ReentrantLockInterrupt implements Runnable{ 
     /** * 定义两个锁,模拟响应中断 */ private static ReentrantLock reentrantLock1 = new ReentrantLock(); private static ReentrantLock reentrantLock2 = new ReentrantLock(); /** * 增加一个标识表名哪个设置中断响应所 */ private String lockFlag; public ReentrantLockInterrupt(String lockFlag) { 
     this.lockFlag = lockFlag; } public void run() { 
     try { 
     //lockFlag = 1则先设置reentrantLock1中断锁 //否则reentrantLock2 设置中断锁 if ("1".equals(lockFlag)){ 
     reentrantLock1.lockInterruptibly(); Thread.sleep(500); reentrantLock2.lockInterruptibly(); System.out.println("reentrantLock1执行"); }else { 
     reentrantLock2.lockInterruptibly(); Thread.sleep(500); reentrantLock1.lockInterruptibly(); System.out.println("reentrantLock2执行"); } } catch (InterruptedException e) { 
     e.printStackTrace(); } finally { 
     //要下判断是否获取当前线程的锁,若是则释放掉 if (reentrantLock1.isHeldByCurrentThread()){ 
     reentrantLock1.unlock(); System.out.printf("释放当前锁reentrantLock1"); } if (reentrantLock2.isHeldByCurrentThread()){ 
     reentrantLock2.unlock(); System.out.println("释放当前锁reentrantLock2"); } } } } 

上例再执行是会出现死锁现象,因两个线程一个走if一个走else,都会拿到对方需要的锁谁都不会释放,直到一个线程中断另一个才会执行。

/** * @Description : * @author : Erick * @time :2018-9-25 */ public class ReentrantLockInterruptTest { 
     public static void main(String[] args) throws InterruptedException { 
     ReentrantLockInterrupt reentrantLockInterrupt1 = new ReentrantLockInterrupt("1"); ReentrantLockInterrupt reentrantLockInterrupt2 = new ReentrantLockInterrupt("2"); //这里新定义两个线程Thread为了使用interrupt方法对线程进行中断 Thread thread1 = new Thread(reentrantLockInterrupt1); Thread thread2 = new Thread(reentrantLockInterrupt2); thread1.start(); thread2.start(); Thread.sleep(1000); thread2.interrupt(); } } 

测试用例中thread1请求if,thread2请求else,启动两个线程同时获取锁出现死锁,然后再休眠1s,确保都拿到锁了方便演示,执行情况如下:

释放当前锁reentrantLock2 java.lang.InterruptedException reentrantLock1执行 at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222) at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335) at com.erick.study.reentrantlock.thread.ReentrantLockInterrupt.run(ReentrantLockInterrupt.java:41) at java.lang.Thread.run(Thread.java:745) 释放当前锁reentrantLock1释放当前锁reentrantLock2 

线程2被中断抛出异常,线程1拿到锁可以顺利执行。

等待锁tryLock

有两种方式:1、无参即尝试获取锁获取不到则直接返回,2、设置等待时间超过时间后还是无法获取到则返回,否则获取锁执行。

/** * @author : Erick * @version : 1.0 * @Description : * @time :2018-9-30 */ public class ReentrantLockTryLock implements Runnable{ 
     private ReentrantLock reentrantLock = new ReentrantLock(); private int i = 0; public void run() { 
     for (int j = 0; j < 10; j++) { 
     try { 
     //设置等待时间为1秒 if (reentrantLock.tryLock(1,TimeUnit.SECONDS)){ 
     i++; System.out.println(Thread.currentThread().getName()+"当前值:"+i); //设置休眠时间 Thread.sleep(500); }else { 
     System.out.println(Thread.currentThread().getName()+"无法获取锁"); } } catch (Exception e) { 
     e.printStackTrace(); System.out.printf("异常"+e.getMessage()); } finally { 
     if (reentrantLock.isHeldByCurrentThread()){ 
     reentrantLock.unlock(); } } } } } 

tryLock不设置等待时间,执行都能获取到锁交替运行,而加上等待时间后会等待一段时间若还是获取不到锁则打印无法获取锁,测试类

/** * @author : Erick * @version : 1.0 * @Description : * @time :2018-9-30 */ public class ReetrantLockTryLockTest { 
     public static void main(String[] args) { 
     ReentrantLockTryLock reentrantLockTryLock = new ReentrantLockTryLock(); Thread thread1 = new Thread(reentrantLockTryLock); Thread thread2 = new Thread(reentrantLockTryLock); thread1.setName("thread1"); thread2.setName("thread2"); thread1.start(); thread2.start(); } } 

公平锁

公平锁是按照进入队列的先后顺序执行的,因为Demo比较简单,每次执行的结果也不一样。

/** * @author : Erick * @version : 1.0 * @Description : * @time :2018-9-30 */ public class ReentrantLockFair implements Runnable{ 
     //实例化指定公平锁方式 private ReentrantLock reentrantLock = new ReentrantLock(true); public void run() { 
     for (int j = 0; j < 10000; j++) { 
     try { 
     reentrantLock.lock(); System.out.println(Thread.currentThread().getName()+"获取锁"); } catch (Exception e) { 
     e.printStackTrace(); } finally { 
     reentrantLock.unlock(); } } } } 

比较简单获取锁,然后输出运行的线程名称,测试类

/** * @author : Erick * @version : 1.0 * @Description : * @time :2018-9-30 */ public class ReentrantLockFairTest { 
     public static void main(String[] args) { 
     ReentrantLockFair reentrantLockFair = new ReentrantLockFair(); Thread thread1 = new Thread(reentrantLockFair); Thread thread2 = new Thread(reentrantLockFair); thread1.start(); thread2.start(); } } 

执行结果,粘贴部分结果

Thread-0获取锁 Thread-0获取锁 Thread-0获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 Thread-0获取锁 Thread-1获取锁 

以上是整理的关于重入锁ReentrantLock的几个简单的Demo,如有不妥之处也请指正。
源代码可以从GitHub或者码云上下载。

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

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/183277.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Android语音采集两种方式MediaRecorder和AudioRecord

    Android语音采集两种方式MediaRecorder和AudioRecord

  • 单臂路由实现VLAN间通信

    单臂路由实现VLAN间通信使用原因以太网中使用VLAN技术隔离二层广播域,其导致不同VLAN之间不能直接通信。在现实中,通常会有跨VLAN通信的情况,单臂路由技术就是解决VLAN间通信的一种方法。单臂路由原理单臂路由的原理是通过一台路由器,使VLAN间通过路由器的三层转发能够互通数据,在路由器的一个物理接口通过配置子接口(即逻辑接口)的方式来实现以一当多的功能、路由器同一物理接口的不同子接口作为不同VLAN的默认网关…

  • 灵格斯:很好很强大的免费电子辞典「建议收藏」

    灵格斯:很好很强大的免费电子辞典「建议收藏」http://www.readfree.net/htm/200807/4624781.html 本文向大家推介近年来出现的国产免费电子辞典软件“灵格斯”(Lingoes),分为四个部分。首先是基本介绍,然后把它和几款同类软件进行了比较,接下来分享我在实用中发现的3个技巧,最后总结了有关的网址链接。本文以主观片面为原则,效果如何,请指教。1.介绍=============

  • msfconsole使用教程_kali msfconsole

    msfconsole使用教程_kali msfconsole文章目录前言一、入侵步骤二、msfconsole常用命令总结前言MetasploitFramework是非常优秀的开源渗透测试框架。Metasploit渗透测试框架(MSF3.4)包含3功能模块:msfconsole、msfweb、msfupdate。msfupdate用于软件更新,建议使用前先进行更新,可以更新最新的漏洞库和利用代码。msfconsole是整个框架中最受欢迎的模块,个人感觉也是功能强大的模块,所有的功能都可以该模块下运行。msfweb是Metasploitframew.

  • 【已解决】罗技K380蓝牙键盘可以连接电脑,但无法输入怎么办?[通俗易懂]

    【已解决】罗技K380蓝牙键盘可以连接电脑,但无法输入怎么办?[通俗易懂]【问题】罗技k380可以连接并正常使用平板、手机。电脑显示着已连接,但就是无法输入。之前是可以用的,最近需要频繁配对突然不能用了。网上的各种方法都不好使,问京东客服也解决不了准备申请售后。【解决方案】后来仔细看了下k380使用方法,发现Fn+F1可以重置键盘的蓝牙设备,于是在电脑删除了k380蓝牙设备后,在蓝牙键盘上进行了Fn+F1重置,最后进行重启配对就ok了。可能是频繁配对让键盘有了缓存错误了。

    2022年10月16日
  • PyCharm插件安装「建议收藏」

    PyCharm插件安装「建议收藏」PyCharm插件安装环境:PyCharm2018.2.2(ProfessionalEdition)Windows101、查看电脑Pycharm版本:【help】->【about】查看pycharm版本2、pycharm插件搜索并安装:【file】->【settings】->【Plugins】进入插件导览界面;点击【BrowseJetBrain…

发表回复

您的电子邮箱地址不会被公开。

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