来自于Herlihy的多处理编程艺术:
假设一个线程想要等待直到某个属性被保存。线程在保存锁时测试属性。如果属性不保存,则线程调用等待()释放锁并休眠,直到被另一个线程唤醒为止。 1条件条件= mutex.newCondition();2.3 mutex.lock() 4尝试{5,而(!属性){ //不高兴6 condition.await();//等待属性7}condition.await (InterruptedException e) {8. //依赖于应用程序的响应9} 10 . //快乐:属性必须持有11 } 图8.2如何使用条件对象。
为什么线程在测试属性之前调用mutex.lock()
(如果属性不保持,则线程调用await()
)而不是之后?
谢谢。
发布于 2017-10-09 00:23:42
如果您将此更改为:
while (!property) {
mutex.lock();
condition.await();
mutex.unlock();
最大的问题是如果属性的值在行之间发生变化。
while (!property) {
还有这条线
mutex.lock();
然后,当该属性已处于过载状态时,您将等待其更改。
如果假设您只能在保持互斥锁的同时更改属性,那么对于问题中的示例,您不能调用
condition.await();
当属性处于过路状态时。
为了详细说明这一假设,问题中的示例代码通常会与设置属性值的某种方式并驾齐驱。这可能是沿着…
void setProperty(boolean newproperty) {
mutex.lock();
property = newproperty;
condition.signalAll();
mutex.unlock();
}
没有这第二部分,你永远无法保证你只打电话给他。
condition.await();
而财产是假的。
发布于 2017-10-09 01:21:52
获取锁的一件事是创建一个内存屏障,这样就不会使用可能已经过时的缓存值来检查条件。
另外,获取锁确保检查的值不会被其他线程并发更改。否则,线程可以测试条件并继续获取锁,然后在获得锁时查找更改的条件。无论如何,线程都需要检查所持有的锁。
线程想要确定锁定对象的状态,然后修改该状态,同时确保该状态不会由于另一个线程的干扰而从状态下改变。这意味着它必须保持锁跨越检查和行动。线程在不成功的检查后等待(释放锁直到发出信号),然后在下一次检查之前获得锁。一旦检查成功,那么它就会保持锁,直到它能够完成对锁定对象的操作。
只有当检查成功时(例如添加到有界缓冲区),对锁定对象执行的操作才有意义。或者,该操作可能涉及多个更改,其中所有更改都需要一起应用(如果锁定对象的数据结构不是为并发访问(如ArrayList )设计的,则该数据结构需要采取多个步骤来添加元素,并且干扰会破坏数据结构)。
https://stackoverflow.com/questions/46637217
复制相似问题