处理虚假唤醒的正确方法是什么?

时间:2015-12-21 15:28:41

标签: java multithreading wakeup

我正在阅读Curator的源代码,并在下面找到了一些代码:

            while ( (client.getState() == CuratorFrameworkState.STARTED) && !haveTheLock )
        {
            List<String>        children = getSortedChildren();
            String              sequenceNodeName = ourPath.substring(basePath.length() + 1); // +1 to include the slash

            PredicateResults    predicateResults = driver.getsTheLock(client, children, sequenceNodeName, maxLeases);
            if ( predicateResults.getsTheLock() )
            {
                haveTheLock = true;
            }
            else
            {
                String  previousSequencePath = basePath + "/" + predicateResults.getPathToWatch();

                synchronized(this)
                {
                    try 
                    {
                        // use getData() instead of exists() to avoid leaving unneeded watchers which is a type of resource leak
                        client.getData().usingWatcher(watcher).forPath(previousSequencePath);
                        if ( millisToWait != null )
                        {
                            millisToWait -= (System.currentTimeMillis() - startMillis);
                            startMillis = System.currentTimeMillis();
                            if ( millisToWait <= 0 )
                            {
                                doDelete = true;    // timed out - delete our node
                                break;
                            }

                            wait(millisToWait);
                        }
                        else
                        {
                            wait();
                        }
                    }
                    catch ( KeeperException.NoNodeException e ) 
                    {
                        // it has been deleted (i.e. lock released). Try to acquire again
                    }
                }
            }
        }

我从Object读取了javadoc,并且应该始终检查循环中的条件,如下所示:

 synchronized (obj) {
     while (condition does not hold&)
        obj.wait(timeout);
         ... // Perform action appropriate to condition
 }

哪个代码是对的?

更新

HereCurator的源代码。

因为haveTheLock是一个局部变量,所以没有其他线程会改变它,所以代码工作正常。

1 个答案:

答案 0 :(得分:0)

同步块

中是

它有两个分支:

  • 无限wait():无条件检查
  • 定时wait(millisToWait),每次循环时重新计算等待毫秒数

所以虚假的唤醒不会产生任何影响。在javadoc中将while循环置于同步块的主要原因是,通常需要同步以确保条件的结果可见。

在您显示的代码中,我的意思是client.getState()haveTheLock都应该是线程安全的(例如volatile变量)。