Condition.await和Object.wait
我们发现 ArrayBlockingList
并没有使用 Object.wait
,而是使用的 Condition.await
,这是为什么呢?其中又有哪些原因呢?
Condition
对象可以提供和 Object
的 wait
和 notify
一样的行为,但是后者必须使用 synchronized
这个内置的monitor锁,而 Condition
使用的是 RenentranceLock
。这两种方式在阻塞等待时都会将相应的锁释放掉,但是 Condition
的等待可以中断,这是二者唯一的区别。
[转载的源码分析]
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//在condition wait队列上添加新的节点
Node node = addConditionWaiter();
//释放当前持有的锁
int savedState = fullyRelease(node);
int interruptMode = 0;
//由于node在之前是添加到condition wait queue上的,现在判断这个node
//是否被添加到Sync的获得锁的等待队列上。
//node在condition queue上说明还在等待事件的notify,
//notify函数会将condition queue 上的node转化到Sync的队列上。
while (!isOnSyncQueue(node)) {
//node还没有被添加到Sync Queue上,说明还在等待事件通知
//所以调用park函数来停止线程执行
LockSupport.park(this);
//判断是否被中断,线程从park函数返回有两种情况,一种是
//其他线程调用了unpark,另外一种是线程被中断
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
//代码执行到这里,已经有其他线程调用notify函数,或则被中断,该线程可以继续执行,但是必须先
//再次获得调用await函数时的锁.acquireQueued函数在AQS文章中做了介绍.
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
reportInterruptAfterWait(interruptMode); //
....
}
signal
函数将等待事件最长时间的线程节点从等待condition的队列移动到获得lock的等待队列中.
public final void signal() {
//
if (!isHeldExclusively())
//如果当前线程没有获得锁,抛出异常
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
//将Condition wait queue中的第一个node转移到acquire lock queue中.
doSignal(first);
}
private void doSignal(Node first) {
do {
//由于生产者的signal在有消费者等待的情况下,必须要通知
//一个消费者,所以这里有一个循环,直到队列为空
//把first 这个node从condition queue中删除掉
//condition queue的头指针指向node的后继节点,如果node后续节点为null,那么也将尾指针也置为null
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
//transferForSignal将node转而添加到Sync的acquire lock 队列
}
final boolean transferForSignal(Node node) {
//如果设置失败,说明该node已经被取消了,所以返回false,让doSignal继续向下通知其他未被取消的node
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
//将node添加到acquire lock queue中.
Node p = enq(node);
int ws = p.waitStatus;
//需要注意的是这里的node进行了转化
//ws>0代表canceled的含义所以直接unpark线程
//如果compareAndSetWaitStatus失败,所以直接unpark,让线程继续执行await中的
//进行isOnSyncQueue判断的while循环,然后进入acquireQueue函数.
//这里失败的原因可能是Lock其他线程释放掉了锁,同步设置p的waitStatus
//如果compareAndSetWaitStatus成功了呢?那么该node就一直在acquire lock queue中
//等待锁被释放掉再次抢夺锁,然后再unpark
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
相关推荐
condition) wait()`来避免“虚假唤醒”问题,即使在没有被唤醒的情况下,线程也会再次检查条件。 在名为`MyTest`的代码文件中,我们可以找到具体的实现示例。这个文件很可能是包含了测试代码,用来演示如何通过主线...
通过使用wait()、notify()和notifyAll(),或者Lock和Condition,开发者可以控制线程的执行顺序,确保共享资源的安全访问。 7. **死锁和活锁问题**: 使用wait/notify机制时,需要注意死锁和活锁问题。死锁发生在两...
Java程序并发的Wait-Notify机制是Java多线程编程中的一种重要同步工具,它允许线程之间通过共享对象进行通信和协作。这个机制基于Java的内置锁(也称为监视器锁),通常与`synchronized`关键字一起使用。在Java中,`...
在给定的代码示例中,我们看到了一个模拟家庭共享同一银行账户的场景,通过使用Java多线程的wait()和notify()方法来控制不同线程(代表家庭成员)的操作顺序。这里涉及到的关键知识点包括: 1. **Java多线程**:...
Condition_Variable 的 wait() 函数使用 pthread_cond_wait() 函数来实现等待操作,而 notify_one() 和 notify_all() 函数使用 pthread_cond_signal() 和 pthread_cond_broadcast() 函数来实现通知操作。 Condition...
在这个例子中,`condition`是线程等待的条件,`object`是调用`wait()`和`notify()`的对象。当条件不满足时,线程进入等待状态,直到其他线程改变了条件并唤醒它。使用`while`循环可以确保线程在条件满足时才会继续...
`Condition`接口提供了类似`wait()`, `notify()`, `notifyAll()`的功能,但与`Lock`对象关联,提供了更好的可读性和可控性。 总之,`wait()`, `notify()`, 和 `notifyAll()` 在Java多线程编程中扮演着核心角色,...
public class ThreadWaitNotify { public static void main(String[] args) throws InterruptedException { DemoTest demoTest = new DemoTest(); // 使用线程池异步执行waitTest方法 ExecutorService ...
在Java的并发编程中,条件变量是一种非常重要的同步工具,它允许线程在某些条件不...而对于简单的同步需求,Object.wait/notify可能更为合适。通过合理使用这些同步工具,我们可以有效地解决并发编程中的线程安全问题。
4.线程间通信:lock、condition、wait、notify、notifyAll 5.Lock-free:atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList 6.关于锁的经验介绍 7.并发流程控制手段:CountDownLatch、Barrier 8.定时器:...
std::condition_variable 的 wait 函数将当前线程阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。 notification 函数有两种形式:notify_one() 和 notify_...
Condition对象,也被称作条件变量,它不仅包含了与锁(Lock)相似的acquire()和release()方法,而且额外提供了wait()和notify()方法。Condition的作用是在线程之间进行更细粒度的协调和控制。 使用Condition实现...
在Java多线程编程中,`Condition`是Java并发包`java.util.concurrent.locks`中的一个接口,它提供了比`Object`类中的`wait()`、`notify()`和`notifyAll()`更加灵活和强大的线程间通信机制。`Condition`与`Lock`配合...
1. `wait(timeout=None)`:让当前持有锁的线程等待,直到其他线程调用`notify()`或`notify_all()`,或者超时(如果指定了`timeout`参数)。超时后,线程会自动返回,即使没有其他线程唤醒它。 2. `notify()`:唤醒...
2. **等待/通知机制**:`Condition`提供了`await()`、`signal()`和`signalAll()`方法,它们类似于`synchronized`块中的`wait()`、`notify()`和`notifyAll()`。但是,`Condition`的这些方法需要在持有相应`Lock`的...
4、线程间的协调手段:lock、condition、wait、notify、notifyAll☆☆☆ 5、Lock-free: atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList☆☆☆ 6、关于锁使用的经验介绍 7、并发流程控制手段:...
此外,`Condition` 还提供了 `wait()` 和 `notify()`(以及 `notify_all()`)方法,这些方法允许线程等待条件满足或通知其他等待的线程。 ### 区别 与简单的锁相比,条件同步的主要区别在于它可以指定线程等待的...
4、线程间的协调手段:lock、condition、wait、notify、notifyAll☆☆☆ 5、Lock-free: atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList☆☆☆ 6、关于锁使用的经验介绍 7、并发流程控制手段:...
使用Condition重写waitnotify案例并实现一个有界队列.mp4 深入解析Condition源码.mp4 实战:简易数据连接池.mp4 线程之间通信之join应用与实现原理剖析.mp4 ThreadLocal 使用及实现原理.mp4 并发工具类...