繁体   English   中英

使用'this'与另一个对象锁定同步块中的wait和notify

[英]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
}

如果没有这个,您将容易受到虚假唤醒的攻击(并非所有通知都来自您的应用程序代码),并且调用waitnotify的顺序会出现问题(如果您有两个线程,并且在另一个等待之前通知,那么通知永远不会被看到)。

无论如何,我建议使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM