[英]Using 'this' versus another object as lock in synchronized block with wait and notify
我有两个代码块,一个等待另一个通知它。
synchronized(this) {
wait();
}
和
while(condition) {
//do stuff
synchronized(this) {
notify();
}
}
奇怪的是,在这样做时没有等待通知:
synchronized(objectLock) {
objectLock.wait();
}
和
while(condition) {
//do stuff
synchronized(objectLock) {
objectLock.notify();
}
}
我对这两组的差异非常好奇,为什么第一组有效,而另一组没有。 请注意,这两个块位于两个不同方法的两个不同线程中(如果这有帮助)。
我希望有人可以解释为什么会这样。 我编辑了我的问题所以它会更加详细。
您可以使用任何您喜欢的对象。 但是,其他程序员通常更清楚地看到显式锁对象。
我的胡乱猜测,为什么this
不适合你的工作是你有不同的this
范围。 (即,在匿名函数/回调中)。 您可以通过附加类名来明确说明要使用哪个类,例如, WonderClass.this
- this
也是为什么this
不清楚的原因。 (编辑:实际上是WhateverClass.this
如果this
真的是一个不同的实例, this
对你没有帮助)
另请阅读: http : //docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html - 我通常会发现将所有线程不安全的代码放入小型同步方法(执行隐含锁定)更容易在此)
它没有工作,因为你在同步this
这两个不同的线程指出,两个不同的 Thread
对象。
与wait()
和notify()
同步只有在同一个对象上进行同步锁定时才能正常工作,就像稍后使用的objectLock
一样。
编辑:如果两个线程实例属于同一个MyThread
类,那么为了达到您认为代码所具有的效果,您必须获取其类对象本身的锁定:
synchronized(MyThread.class)
当你说这两个块存在于两个不同的线程中时,我认为它们并没有锁定在同一个对象上,因为this
不是一回事。 当您命名一个显式锁定时,您使用相同的东西来锁定。
顺便说一下,你应该在循环中调用wait
,如下所示:
synchronized(someLock) {
while (!someCondition) {
wait();
}
// now the thread has the lock and it can do things
// knowing for sure that someCondition is true
}
如果没有这个,您将容易受到虚假唤醒的攻击(并非所有通知都来自您的应用程序代码),并且调用wait
和notify
的顺序会出现问题(如果您有两个线程,并且在另一个等待之前通知,那么通知永远不会被看到)。
无论如何,我建议使用Monitor模式( http://en.wikipedia.org/wiki/Monitor_(synchronization) ),这可以避免以后的错误,特别是当您的用例变得更复杂时:
class Monitor
{
/** Initialised to `false` by default in Java. */
boolean condition;
synchronized void waitForSomething()
{
while(!condition)
{
wait();
}
}
synchronized void signal()
{
condition = true;
notify();
}
}
这样一切都很好地封装和保护(我通常不会在示例中使用private
修饰符,但您可能希望在代码中强制执行额外的“隐私”,特别是将condition
private
。)
正如你所看到的,在我的条件循环中有wait()
调用,而不是你在循环中有notify()
例子。 在大多数用例中,使用notify
做的事情是错误的,虽然我不能代表您的具体情况,因为您没有向我们提供足够的详细信息。 我愿意打赌你的是典型的,其中Monitor模式适用得很漂亮。
使用场景如下:想要等待某事的线程调用waitForSomething
而另一个线程可能通过调用将设置条件标志的signal
方法使其继续。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.