|
|
51CTO旗下网站
|
|
移动端

1.7.7 Condition条件变量

《Java多线程与Socket:实战微服务框架》第1章多线程基础,本书尽量采用简要和通俗易懂的方式来介绍多线程知识。本节为大家介绍Condition条件变量。

作者:庞永华来源:电子工业出版社|2019-03-26 16:00

1.7.7 Condition条件变量

synchronized的同步机制要求所有线程等待同一对象的监视器“锁”标记。在通过wait()/signal()/signalAll()方法进行通信时,只能随机唤醒这些线程之一,无法有选择地通知要唤醒哪些线程,也无法避免某些线程因为“运气不佳”而长时间得不到执行的问题。因此,这种内置锁是一种粗粒度的非公平锁。

ReentrantLock允许开发者根据实际情况,创建多个条件变量(Condition),线程可以根据需要在不同的Condition上执行await()/signal()/signalAll()方法,以实现在synchronized同步块中调用作为锁的对象的wait()/notify()/notifyAll()方法的相似功能。

首先,和wait()方法一样,await()方法也能响应线程中断(线程的interrupt()方法)。其次,Condition的await()/signal()方法需要在当前线程取得了当前Condition对象所对应的Lock锁时才能使用。这与wait()/notify()方法需要先获得对象的内置锁类似。主要区别在于一个Lock可以用多个Condition,并且await()/signal()方法都是面向Condition而不是Lock锁的。也就是说,signal()方法只会通知在同一个Condition上执行了await()的线程。

每个Condition对象拥有一个队列。一旦线程调用Condition对象的await() 方法,当前线程将被挂起并登记到此队列。signal()方法负责从队列取出一个线程并唤醒。signalAll()方法则会将队列中的所有线程按先入先出的顺序全部取出并唤醒。ReentrantLock允许通过构造函数的参数来指定是否为公平锁。如果当前ReentrantLock对象使用了公平锁,则当前线程将被添加到Condition的挂起线程队列尾,以确保等待最久的线程***被取出并唤醒。反之,将不保证线程的入队顺序。

请运行并思考下面的示例:

  1. public class C1_7_7 implements Runnable {  
  2. private static final Logger log = LoggerFactory.getLogger(C1_7_7.class);  
  3. private static final Lock lock = new ReentrantLock();  
  4. private static final Condition condition1 = lock.newCondition();  
  5. private static final Condition condition2 = lock.newCondition();  
  6. private boolean flag;  
  7. public C1_7_7(boolean flag) {  
  8. this.flag = flag;  
  9. }  
  10. public void run() {  
  11. lock.lock();  
  12. try {  
  13. if (flag) {  
  14. log.info("Before condition1.await()");  
  15. condition1.await();  
  16. log.info("After condition1.await()");  
  17. } else {  
  18. log.info("Before condition2.await()");  
  19. condition2.await();  
  20. log.info("After condition2.await()");  
  21. }  
  22. } catch (InterruptedException e) {  
  23. e.printStackTrace();  
  24. } finally {  
  25. lock.unlock();  
  26. }  
  27. }  
  28. public static void main(String[] args) throws InterruptedException {  
  29. ExecutorService es = Executors.newCachedThreadPool();  
  30. es.execute(new C1_7_7(true));  
  31. es.execute(new C1_7_7(false));  
  32. es.execute(new Runnable() {  
  33. @Override  
  34. public void run() {  
  35. boolean b = false; //换成true试试  
  36. lock.lock();  
  37. try {  
  38. Thread.sleep(1000L);  
  39. log.info("condition1.signalAll()");  
  40. condition1.signalAll();  
  41. if (b) {  
  42. Thread.sleep(2000L);  
  43. log.info("condition2.signalAll()");  
  44. condition2.signalAll();  
  45. return;  
  46. }  
  47. } catch (InterruptedException e) {  
  48. e.printStackTrace();  
  49. } finally {  
  50. lock.unlock();  
  51. }  
  52. // condition2  
  53. lock.lock();  
  54. try {  
  55. Thread.sleep(2000L);  
  56. log.info("condition2.signalAll()");  
  57. condition2.signalAll();  
  58. } catch (InterruptedException e) {  
  59. e.printStackTrace();  
  60. } finally {  
  61. lock.unlock();  
  62. }  
  63. }  
  64. });  
  65. es.shutdown();  
  66. }  


喜欢的朋友可以加入官方的读书群

51CTO读书频道二维码


51CTO读书会第9群:808517103

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+更多

16招轻松掌握PPT技巧

16招轻松掌握PPT技巧

GET职场加薪技能
共16章 | 晒书包

289人订阅学习

20个局域网建设改造案例

20个局域网建设改造案例

网络搭建技巧
共20章 | 捷哥CCIE

645人订阅学习

WOT2019全球人工智能技术峰会

WOT2019全球人工智能技术峰会

通用技术、应用领域、企业赋能三大章节,13大技术专场,60+国内外一线人工智能精英大咖站台,分享人工智能的平台工具、算法模型、语音视觉等技术主题,助力人工智能落地。
共50章 | WOT峰会

0人订阅学习

读 书 +更多

信息安全风险评估

信息安全风险评估理论研究日趋成熟,相关资料比较充分,但有关评估实际工作的参考资料很少。本书以信息安全风险评估实践为基础,围绕评估工...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO播客