返回顶部
首页 > 资讯 > 精选 >类似Object监视器方法的Condition接口(详解)
  • 449
分享到

类似Object监视器方法的Condition接口(详解)

object监视器condition 2023-05-31 13:05:30 449人浏览 独家记忆
摘要

在《基于线程、并发的基本概念(详解)》中,我们利用synchronized关键字、Queue队列、以及Object监视器方法实现了生产者消费者,介绍了有关线程的一些基本概念。Object类提供的wait的方法和notifyAll方法,与之对

在《基于线程并发的基本概念(详解)》中,我们利用synchronized关键字、Queue队列、以及Object监视器方法实现了生产者消费者,介绍了有关线程的一些基本概念。Object类提供的wait的方法和notifyAll方法,与之对应的是Condition接口提供是await和signalAll。await(或wait)是让当前线程进入等待状态并释放,signalAll(或notifyAll)则是唤醒等待中的线程,使得等待中的线程有竞争锁的资格,注意只是资格,并不代表被唤醒的线程就一定会获得锁。

Condition接口的具体实现还是在AbstractQueuedSynchronizer中的内部实现的——AbstractQueuedSynchronizer$ConditionObject。ConditionObject中维护了一个“等待队列”,注意这个和AQS同步器维护的“同步队列”不同。AQS所维护的同步队列是当前等待资源(同步状态)的队列,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成一个节点并加入到同步队列中,同时阻塞当前线程,当同步状态被所持有的线程释放时会将同步队列中的首节点唤醒重新获取同步状态。而每个Condition维护一个等待队列,该队列的作用是一个等待signal信号的队列。这两者之间的关系是一个协同的关系,用下图的说明它们之间的协同过程:

AQS的同步队列如下图所示,一个头结点head指向队首,一个tail指向队尾,当线程调用lock()方法获取锁而未成功时,线程被构造成节点加入到队尾。(图中nodeA是同步队列的第一个节点,也就是获得同步状态的节点)

类似Object监视器方法的Condition接口(详解)

NodeA调用await()方法时,NodeA从AQS同步队列中移除,自然也就释放了锁,NodeA此时被加入到Condition的等待队列中,等待signal信号,如下图所示。

  类似Object监视器方法的Condition接口(详解)

执行完第2步后,此时NodeB在同步队列中处于第一个节点位置,即获取到了锁,如果NodeB此时执行signal(或者signalAll)方法,NodeA将会从Condition等待队列中被移除即被唤醒,加入到同步队列中,此时NodeA仅仅是被唤醒有了在同步队列中争夺资源的资格,并不代表被唤醒后就立即获得锁,如下图所示。

类似Object监视器方法的Condition接口(详解)

最后NodeB在signal执行完毕后,调用unLock方法释放锁,此时NodeA处于队首,并争夺同步状态。

以上是AQS的“同步队列”和Condition的“等待队列”之间相互协作的过程,下面从源码解析Condition的主要方法await、signal、signalAll。

public final void await() throws InterruptedException{ if (Thread.interrupted()) //线程被中断则抛出中断异常 throw new InterruptedException(); Node node = addConditionWaiter(); //将线程构造为Node节点 long savedState = fullyRelease(node); //释放锁,返回同步状态 int interruptMode = 0; while (!isOnSyncQueue(node)) { //循环判断当前节点是否在同步队列中 LockSupport.park(this); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)  break; //检查节点在处于等待状态时是否被中断  }  //在跳出了循环,即被signal唤醒后重新加入了同步队列后,开始重新竞争锁  if (acquireQueued(node, savedState) && interruptMode != THROW_IE) //acquireQueued自旋获取锁,具体分析见《2.从AbstractQueuedSynchronizer(AQS)说起(1)——独占模式的锁获取与释放》中对获取同步状态的解析    interruptMode = REINTERRUPT;   if (node.nextWaiter != null)    unlinkCancelledWaiters(); //如果节点从等待状态转换为在同步队列中,并且也已经获得了锁,此时将断开此节点后面的等待节点  if (interruptMode != 0)   reportInterruptAfterWait(interruptMode); }

--结束END--

本文标题: 类似Object监视器方法的Condition接口(详解)

本文链接: https://lsjlt.com/news/225900.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作