重入锁和读写锁

逃离我推掉我的手 2023-06-16 04:59 79阅读 0赞

   在java多线程中,我们知道可以用synchronize关键字来实现线程间的同步互斥工作,还有更加优秀的机制去实现同步互斥工作,Lock对象。重入锁和读写锁,他们具有比synchronize更加强大的功能,并且具有嗅探锁定,多路分支等功能。
一、ReentrantLock(重入锁)(详见JDK-API)

  1. public class UseReentrantLock {
  2. private Lock lock = new ReentrantLock();
  3. public void method1(){
  4. try {
  5. lock.lock();
  6. System.out.println("当前线程:" + Thread.currentThread().getName() + "进入method1..");
  7. Thread.sleep(1000);
  8. System.out.println("当前线程:" + Thread.currentThread().getName() + "退出method1..");
  9. Thread.sleep(1000);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. } finally {
  13. lock.unlock();
  14. }
  15. }
  16. public void method2(){
  17. try {
  18. lock.lock();
  19. System.out.println("当前线程:" + Thread.currentThread().getName() + "进入method2..");
  20. Thread.sleep(2000);
  21. System.out.println("当前线程:" + Thread.currentThread().getName() + "退出method2..");
  22. Thread.sleep(1000);
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. } finally {
  26. lock.unlock();
  27. }
  28. }
  29. public static void main(String[] args) {
  30. final UseReentrantLock ur = new UseReentrantLock();
  31. Thread t1 = new Thread(new Runnable() {
  32. @Override
  33. public void run() {
  34. ur.method1();
  35. ur.method2();
  36. }
  37. }, "t1");
  38. t1.start();
  39. try {
  40. Thread.sleep(10);
  41. } catch (InterruptedException e) {
  42. e.printStackTrace();
  43. }
  44. //System.out.println(ur.lock.getQueueLength());
  45. }
  46. }

二、锁的等待与通知
  在使用synchronize的时候,如果需要多线程之间进行协作工作,则需要Object的wait()和notify(),notifyAll( )方法进行配合工作。那么同样,我们在使用Lock的时候,可以使用一个新的等待通知类,它就是Condition,这个Condition一定是针对具体某一把锁的。也就是在只有锁的基础上才会产生Condition。

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

三、多Condition
  我们可以通过一个Lock对象产生多个Condition进行多线程间的交互,非常的灵活。可以使得部分需要唤醒的线程唤醒,其他线程则继续等待通知。

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

四 . Lock / Condition其他方法和用法
   1.公平锁和非公平锁: Lock lock = new ReentrantLock ( boolean isFair);
   lock的用法:
     tryLock():尝试获得锁,获得结果用true/false返回.
      tryLock():在给定的时间内尝试获得锁,获得结果用true/false返回.
      isFair():是否是公平锁
      isLocked():是否锁定
      getHoldCount():查询当前线程保持此锁的个数,也就是调用lock()的次数
      lockInterruptibly:优先响应中断的锁

发表评论

表情:
评论列表 (有 0 条评论,79人围观)

还没有评论,来说两句吧...

相关阅读

    相关

       在java多线程中,我们知道可以用synchronize关键字来实现线程间的同步互斥工作,还有更加优秀的机制去实现同步互斥工作,Lock对象。重入锁和读写锁,他们具有比