简体   繁体   English

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

[英]What's the right way to deal with spurious wakeup?

I am reading Curator 's source code, and found some code below: 我正在阅读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
                    }
                }
            }
        }

I read javadoc from Object and should always check condition in loops, like this : 我从Object读取Javadoc,并且应始终检查循环中的条件,如下所示:

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

which code is right? 哪个代码正确?

Update 更新资料

Here is the source code of Curator . Curator的源代码。

Because haveTheLock is a local variable, no other thread would change it, so the code works fine. 因为haveTheLock是一个局部变量,所以没有其他线程可以更改它,因此代码可以正常工作。

The synchronized block is within a while loop. 同步块一个while循环内。

And it has two branches: 它有两个分支:

  • an infinite wait() : no condition to check 无限的wait() :无条件检查
  • a timed wait(millisToWait) and the amount of millis to wait is recalculated at each loop 一个定时的wait(millisToWait)wait(millisToWait)数在每个循环中重新计算

So spurious wakeups won't really have an effect. 因此,虚假唤醒不会真正起作用。 The main reason to have the while loop inside the synchronized block as in the javadoc is that very often you need the synchronization to make sure the result of the condition is visible. 像Javadoc一样,在同步块使用while循环的主要原因是,经常需要进行同步以确保条件的结果可见。

In the code you show, I means that both client.getState() and haveTheLock should be thread safe (for example volatile variables). 在您显示的代码中,我的意思是client.getState()haveTheLock都应该是线程安全的(例如,volatile变量)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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