java 自旋锁的替代方案

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2173309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 19:51:32  来源:igfitidea点击:

Alternative to spinlock

javauser-interfacesynchronizationspinlock

提问by Aly

I am using the following spinlock approach:

我正在使用以下自旋锁方法:

while(!hasPerformedAction()){
    //wait for the user to perform the action
    //can add timer here too
}

setHasPerformedAction(false);

return getActionPerfomed();

this basically waits for a user to perform an action and then returns it. Currently something requests an answer from the user before continuing, this is why I wait until input is received. However I was wondering if this is inefficient and if we are waiting for a while (i.e. <= 30 secs) will it slow down the pc that is running this app. Are there any other alternatives using this approach i.e. locks, semaphores if so what is the syntax?

这基本上等待用户执行操作然后返回它。目前,在继续之前,有些东西需要用户的回答,这就是我等待直到收到输入的原因。但是我想知道这是否效率低下,如果我们等待一段时间(即 <= 30 秒)会减慢运行此应用程序的 PC 的速度。有没有其他使用这种方法的替代方法,即锁,信号量,如果有的话,语法是什么?

Thanks,

谢谢,

Aly

阿里

回答by Paul Wagland

In fact, not only is this inefficient, it is not even guaranteed to work, since there is no "happens-before" edge in the code that you are showing. To create a happens-before edgeyou need to do one of:

事实上,这不仅效率低下,甚至不能保证工作,因为在您显示的代码中没有“发生在之前”的边缘。要创建发生在边缘之前,您需要执行以下操作之一:

  1. Access a volatile variable
  2. Synchronise on a shared resource
  3. Use a concurrent utils lock.
  1. 访问 volatile 变量
  2. 同步共享资源
  3. 使用并发工具锁。

As mentioned in another comment, the easiestsolution, is simply to ensure that your flag is a volatile variable, and simply throw a short sleep in your loop.

正如另一条评论中提到的,最简单的解决方案就是确保您的标志是一个易失性变量,并在您的循环中进行短暂的睡眠。

However, the best thing to do would be to synchronize/wait/notify on a shared variable.

但是,最好的做法是同步/等待/通知共享变量。

The methods that you need to read up on are waitand notify. For a better description on how to use these, read this article. An example code snippet is shown below;

您需要阅读的方法是waitnotify。有关如何使用这些的更好描述,请阅读这篇文章。下面显示了一个示例代码片段;

Thread 1

主题 1

Object shared = new Object();
startThread2(shared);
synchronized (shared) {
  while (taskNotDone())
    shared.wait();
}

Thread 2

主题 2

// shared was saved at the start of the thread
// do some stuff
markTaskAsDone();
synchronized (shared) {
  shared.notify();
}

回答by SyntaxT3rr0r

What you've written is called busy looping, which you should never do.

你写的东西叫做忙循环,你永远不应该这样做。

You may want to keep doing that, but at least sleep a bit as to not be busy looping, which still wouldn't be that great:

你可能想继续这样做,但至少睡一会儿以免忙于循环,这仍然不会那么好:

while( !hasPerformedAction() ) {
    (sleep a bit here)
}

Another way to do it would to enqueue the user actions on a blocking queue: then you could simply be using a queue.takeand the queue implementation would take care of the issue for you.

另一种方法是将用户操作排入阻塞队列:然后您可以简单地使用queue.take并且队列实现将为您处理这个问题。

And another way would be to use a callback to be notified of the user actions.

另一种方法是使用回调来通知用户操作。

回答by aperkins

The java tutorials have a good lesson on concurrency in java:

Java 教程对 Java 中的并发有很好的教训:

http://java.sun.com/docs/books/tutorial/essential/concurrency/

http://java.sun.com/docs/books/tutorial/essential/concurrency/

If you are going to be modifying UI from another thread, you will want to remember to do:

如果您打算从另一个线程修改 UI,您需要记住:

SwingUtils.invokeLater(actionToInvoke);

回答by Carl Smotricz

There's a guiin your tags, so I'll assume that the action is done in the GUI.

gui您的标签中有 a ,因此我假设该操作是在 GUI 中完成的。

The "recommended" way to do this kind of thing is for the main thread to put itself to sleep (perhaps using wait()) and for the GUI action to notify()it back into wakefulness once the action has been performed.

做这种事情的“推荐”方法是让主线程将自己置于睡眠状态(可能使用wait()),并在执行操作后让 GUI 操作notify()返回唤醒状态。

回答by DerMike

There are some classes for that in java.util.concurrent.locks. Have a look at Class LockSupport

java.util.concurrent.locks. 看看类LockSupport

Regards Mike

问候迈克