ReentrantLock

有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级。

this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决方案,后面jdk干脆就提供了一个Lock类。

伪代码:

Lock lock = new ReentrantLock();//新建一个lock

Condition condition = lock.newCondition();//获取条件

method1(){

  try{

    lock.lock();

    代码块;

    lock.unlock();

    后续代码块;

  }

}

method2(){

  try{

    lock.lock();

    代码块;

    lock.signal();

  }

}

单condition操作:

  1. import java.util.concurrent.locks.Condition;
  2. import java.util.concurrent.locks.Lock;
  3. import java.util.concurrent.locks.ReentrantLock;
  4.  
  5. public class UseCondition {
  6.  
  7. private Lock lock = new ReentrantLock();
  8. private Condition condition = lock.newCondition();
  9.  
  10. public void method1(){
  11. try {
  12. lock.lock();
  13. System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..");
  14. Thread.sleep(3000);
  15. System.out.println("当前线程:" + Thread.currentThread().getName() + "释放锁..");
  16. condition.await(); // Object wait
  17. System.out.println("当前线程:" + Thread.currentThread().getName() +"继续执行...");
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. } finally {
  21. lock.unlock();
  22. }
  23. }
  24.  
  25. public void method2(){
  26. try {
  27. lock.lock();
  28. System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..");
  29. Thread.sleep(3000);
  30. System.out.println("当前线程:" + Thread.currentThread().getName() + "发出唤醒..");
  31. condition.signal(); //Object notify
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. } finally {
  35. lock.unlock();
  36. }
  37. }
  38.  
  39. public static void main(String[] args) {
  40.  
  41. final UseCondition uc = new UseCondition();
  42. Thread t1 = new Thread(new Runnable() {
  43. @Override
  44. public void run() {
  45. uc.method1();
  46. }
  47. }, "t1");
  48. Thread t2 = new Thread(new Runnable() {
  49. @Override
  50. public void run() {
  51. uc.method2();
  52. }
  53. }, "t2");
  54. t1.start();
  55.  
  56. t2.start();
  57. }
  58.  
  59. }

执行结果:

解释:线程1调用method1方法,线程2调用同一对象的method2方法,线程1先启动,线程1获取锁,进入method1的代码块,线程2也启动了,单是线程2被锁定,直到线程1发出lock.unlock()了,线程1才将锁释放,这时线程2获取锁,执行method2的代码块,线程2发出lock.signal(); 线程1才继续执行后续代码块。

多condition操作:

  1. import java.util.concurrent.locks.Condition;
  2. import java.util.concurrent.locks.ReentrantLock;
  3.  
  4. public class UseManyCondition {
  5.  
  6. private ReentrantLock lock = new ReentrantLock();
  7. private Condition c1 = lock.newCondition();
  8. private Condition c2 = lock.newCondition();
  9.  
  10. public void m1(){
  11. try {
  12. lock.lock();
  13. System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m1等待..");
  14. c1.await();
  15. System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m1继续..");
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. } finally {
  19. lock.unlock();
  20. }
  21. }
  22.  
  23. public void m2(){
  24. try {
  25. lock.lock();
  26. System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m2等待..");
  27. c1.await();
  28. System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m2继续..");
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. } finally {
  32. lock.unlock();
  33. }
  34. }
  35.  
  36. public void m3(){
  37. try {
  38. lock.lock();
  39. System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m3等待..");
  40. c2.await();
  41. System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m3继续..");
  42. } catch (Exception e) {
  43. e.printStackTrace();
  44. } finally {
  45. lock.unlock();
  46. }
  47. }
  48.  
  49. public void m4(){
  50. try {
  51. lock.lock();
  52. System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒..");
  53. c1.signalAll();
  54. } catch (Exception e) {
  55. e.printStackTrace();
  56. } finally {
  57. lock.unlock();
  58. }
  59. }
  60.  
  61. public void m5(){
  62. try {
  63. lock.lock();
  64. System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒..");
  65. c2.signal();
  66. } catch (Exception e) {
  67. e.printStackTrace();
  68. } finally {
  69. lock.unlock();
  70. }
  71. }
  72.  
  73. public static void main(String[] args) {
  74.  
  75. final UseManyCondition umc = new UseManyCondition();
  76. Thread t1 = new Thread(new Runnable() {
  77. @Override
  78. public void run() {
  79. umc.m1();
  80. }
  81. },"t1");
  82. Thread t2 = new Thread(new Runnable() {
  83. @Override
  84. public void run() {
  85. umc.m2();
  86. }
  87. },"t2");
  88. Thread t3 = new Thread(new Runnable() {
  89. @Override
  90. public void run() {
  91. umc.m3();
  92. }
  93. },"t3");
  94. Thread t4 = new Thread(new Runnable() {
  95. @Override
  96. public void run() {
  97. umc.m4();
  98. }
  99. },"t4");
  100. Thread t5 = new Thread(new Runnable() {
  101. @Override
  102. public void run() {
  103. umc.m5();
  104. }
  105. },"t5");
  106.  
  107. t1.start(); // c1
  108. t2.start(); // c1
  109. t3.start(); // c2
  110.  
  111. try {
  112. Thread.sleep(2000);
  113. } catch (InterruptedException e) {
  114. e.printStackTrace();
  115. }
  116.  
  117. t4.start(); // c1
  118. try {
  119. Thread.sleep(2000);
  120. } catch (InterruptedException e) {
  121. e.printStackTrace();
  122. }
  123. t5.start(); // c2
  124.  
  125. }
  126.  
  127. }

执行结果:

解释:t1、t2线程都是用第一个condition c1,t3线程用第二个condition c2,t4线程发出c1.signalAll() 唤醒t1和t2线程,t5发出c2.signal()唤醒t3线程。

ReentrantReadWriteLock

读写分离锁,读读共享、写写互斥、读写互斥。

  1. import java.util.concurrent.locks.ReentrantReadWriteLock;
  2. import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
  3. import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
  4.  
  5. public class UseReentrantReadWriteLock {
  6.  
  7. private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
  8. private ReadLock readLock = rwLock.readLock();
  9. private WriteLock writeLock = rwLock.writeLock();
  10.  
  11. public void read(){
  12. try {
  13. readLock.lock();
  14. System.out.println("当前线程:" + Thread.currentThread().getName() + "进入...");
  15. Thread.sleep(3000);
  16. System.out.println("当前线程:" + Thread.currentThread().getName() + "退出...");
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. } finally {
  20. readLock.unlock();
  21. }
  22. }
  23.  
  24. public void write(){
  25. try {
  26. writeLock.lock();
  27. System.out.println("当前线程:" + Thread.currentThread().getName() + "进入...");
  28. Thread.sleep(3000);
  29. System.out.println("当前线程:" + Thread.currentThread().getName() + "退出...");
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. } finally {
  33. writeLock.unlock();
  34. }
  35. }
  36.  
  37. public static void main(String[] args) {
  38.  
  39. final UseReentrantReadWriteLock urrw = new UseReentrantReadWriteLock();
  40.  
  41. Thread t1 = new Thread(new Runnable() {
  42. @Override
  43. public void run() {
  44. urrw.read();
  45. }
  46. }, "t1");
  47. Thread t2 = new Thread(new Runnable() {
  48. @Override
  49. public void run() {
  50. urrw.read();
  51. }
  52. }, "t2");
  53. Thread t3 = new Thread(new Runnable() {
  54. @Override
  55. public void run() {
  56. urrw.write();
  57. }
  58. }, "t3");
  59. Thread t4 = new Thread(new Runnable() {
  60. @Override
  61. public void run() {
  62. urrw.write();
  63. }
  64. }, "t4");
  65.  
  66. t1.start();
  67. t2.start();
  68.  
  69. // t1.start(); // R
  70. // t3.start(); // W
  71.  
  72. // t3.start();
  73. // t4.start();
  74. }
  75. }

解释:t1和t2都是读,是共享的,可同时获得readLock同时进入read方法执行。t1是读和t3是写,是互斥的,只有t1执行完t3才能执行。t3、t4都是写,是互斥的,只有等t3执行完t4才能继续。

架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock的更多相关文章

  1. synchronized关键字,Lock接口以及可重入锁ReentrantLock

    多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...

  2. Java 重入锁 ReentrantLock 原理分析

    1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生 ...

  3. 轻松学习java可重入锁(ReentrantLock)的实现原理

    转载自https://blog.csdn.net/yanyan19880509/article/details/52345422,(做了一些补充) 前言 相信学过java的人都知道 synchroni ...

  4. java 可重入锁ReentrantLock的介绍

    一个小例子帮助理解(我们常用的synchronized也是可重入锁) 话说从前有一个村子,在这个村子中有一口水井,家家户户都需要到这口井里打水喝.由于井水有限,大家只能依次打水.为了实现家家有水喝,户 ...

  5. 轻松学习java可重入锁(ReentrantLock)的实现原理(转 图解)

    前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...

  6. 17_重入锁ReentrantLock

    [概述] 重入锁可以完全代替synchronized关键字. 与synchronized相比,重入锁ReentrantLock有着显示的操作过程,即开发人员必须手动指定何时加锁,何时释放锁,所以重入锁 ...

  7. Java 显示锁 之 重入锁 ReentrantLock(七)

    ReentrantLock 重入锁简介 重入锁 ReentrantLock,顾名思义,就是支持同一个线程对资源的重复加锁.另外,该锁还支持获取锁时的公平与非公平性的选择. 重入锁 ReentrantL ...

  8. 可重入锁ReentrantLock解析

    说到可重入锁,先从AQS的ConditionObject说起,AQS的内部类ConditionObject是构建显示锁条件队列的基础.之前AQS的解析没有说这个内部类,这里和ReentrantLock ...

  9. Java中可重入锁ReentrantLock原理剖析

    本文由码农网 – 吴极心原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 一. 概述 本文首先介绍Lock接口.ReentrantLock的类层次结构以及锁功能模板类AbstractQue ...

随机推荐

  1. JqueryDataTable的使用(.Net平台)

    上一篇随笔提到了MvcPager,最近用到了一款前端JQ插件------DataTable(简称DT),很好用. DT是一款前端插件,和后端完全分离开,就这点来看,我就特别喜欢. 一.使用DT,需要以 ...

  2. 一步步实现ABAP后台导入EXCEL到数据库【1】

    在SAP的应用当中,导入.导出EXCEL文件的情况是一个常见的需求,有时候用户需要将大量数据定期导入到SAP的数据库中.这种情况下,使用导入程序在前台导入可能要花费不少的时间,如果能安排导入程序为后台 ...

  3. MPAndroidChart 3.0——LineChart(折线图)

    显示效果 MPAndroidChart每一种图表的基本使用方式都基本相同 了解一种图表的实现 参考项目源码其他的图表也就差不多哩 在布局文件中定义 <com.github.mikephil.ch ...

  4. 一位资深程序员大牛给予Java初学者的学习路线建议

    java学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是我你是如何学习Java的,能不能给点建议?今天我是打算来点干货,因此咱们就不说一些学习方法和技巧了,直接来谈 ...

  5. 长按TextField或TextView显示中文的粘贴复制

    首先要确保手机当前系统为中文,只需要在 plist 文件中添加 Localized resources can be mixed = YES 就行了

  6. UICollectionViewCell--查找cell上的按钮点击后,对应的是哪个cell

    实际写项目会碰到各种各样的问题,废话不多说 按钮添加到cell时,根据是直接添加到self还是self.contentView上,在点击方法里找到btn的父视图 我是直接添加到self上,所以只有一层 ...

  7. nginx+tomcat https实践

    1. 安装ssl'证书 使用Let's Encrypt 的免费证书: 下载源代码: git clone https://github.com/letsencrypt/letsencrypt 我时阿里云 ...

  8. 国产方法论之 ReDoIt -- 惟思捷

    最近上了PMP课程,感觉受益匪浅,思路有被打开. 很同意一个观点“国人很擅长做事,但是不擅长总结出解决问题的通用框架和方法论”. 为了能提高中小企业生产力我最近成了一个小的软件咨询公司取名“惟思捷”, ...

  9. 基础拾遗------redis详解

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  10. hadoop-2.7.1伪分布环境搭建

    1.准备Linux环境  1.0 点击VMware快捷方式,右键打开文件所在位置 -> 双击vmnetcfg.exe -> VMnet1 host-only ->修改subnet i ...