引用手册页:
使用条件变量时,总会有一个布尔谓词,涉及与每个条件等待关联的共享变量,如果线程应该继续,则为真.可能会发生pthread_cond_timedwait()或pthread_cond_wait()函数的虚假唤醒.由于从pthread_cond_timedwait()或pthread_cond_wait()返回并不意味着有关此谓词的值的任何内容,因此应在返回时重新评估谓词.
因此,pthread_cond_wait即使您没有发信号也可以返回.乍一看,这看起来非常残酷.它就像一个随机返回错误值或在实际到达正确的返回语句之前随机返回的函数.这似乎是一个主要的错误.但是他们选择在手册页中记录这一点而不是修复它的事实似乎表明有一个合理的理由为什么pthread_cond_wait最终虚假地唤醒.据推测,它有一些内在的关于它是如何工作的,这使它无法帮助.问题是什么.
为什么没有pthread_cond_wait虚假回报?为什么它不能保证它只是在它被正确发出信号后醒来?谁能解释其虚假行为的原因?
Java的Object.wait()警告"虚假的唤醒",但C#的Monitor.wait()似乎根本没有提到它.
看看Mono是如何在Linux之上实现的,并且Linux有虚假的唤醒,不应该在某处记录吗?
这个问题不是关于,虚假的唤醒是否真的很开心,因为这已经在这里全面讨论过:虚假的唤醒真的发生了吗?因此,这也不是为什么我必须围绕我的wait声明循环.这是关于:
我想构建一个虚假唤醒发生的案例.到目前为止我在上面提到的问题中学到的是:
如果发出一个Linux进程的信号,它的等待线程将各自享受一个不错的,热的虚假唤醒.
所以看来这只能用于linux机器,实际上我有Ubuntu 11.04 - 64位.我编写了一个Java程序,其中一个线程正在等待一个条件,但没有循环和另一个类,线程只是等待并被另一个线程通知.我认为在一个JVM中启动所有三个线程会强制执行上述情况,但似乎并非如此.
有没有其他人知道如何在Java中构建这样的案例?
自从我写一个分析器注重并发方面,我要寻找使用好的人造例如同步机制中的Java.我的探查器可以看到与线程相关的一些操作; 例如:
所以我正在寻找的是一个Java程序,乍一看似乎是理解的,但在执行它时,你开始怀疑结果.我希望我的探查器可能能够检测到后台发生了什么.
为了澄清自己,我举一个例子,Brian Goetz撰写的Java Concurrency in Practice一书给出了"有毒"代码示例,这些示例用于学习原因.
@NotThreadSafe
public class ListHelper<E> {
public List<E> list =
Collections.synchronizedList(new ArrayList<E>());
...
public synchronized boolean putIfAbsent(E x) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}
Run Code Online (Sandbox Code Playgroud)
这是通过该方法的线程安全类的扩展putIfAbsent.由于list是同步的,但putIfAbsent使用另一个锁来保护状态,就像列表中定义的方法一样.
分析器可以显示使用过的监视器锁和用户的惊讶(或者不是......),用户会看到有两个可能的监视器锁而不是一个.
我不太喜欢这个例子,但我不会问,如果我已经有很多好的例子了.
我发现我的问题类似于:你在Java中遇到的最常见的并发问题是什么?和Java并发错误模式.
但他们只提到破坏的并发程序.我也在寻找线程安全的实现,但仍然不明显它们是线程安全的.
这是我在一些我正在维护的代码中看到的代码片段.
Object lock = new Object();
synchronized( lock )
{
try
{
lock.wait( 50000 );
Thread.sleep( 3000 );
}
catch(Exception ex)
{
}
}
Run Code Online (Sandbox Code Playgroud)
开发人员希望暂停当前线程一段时间,并使用Object#wait作为机制.显然,由于这个原因,使用wait/notify协议是不好的形式; 但是,调用wait(millisec)和Thread.sleep之间有什么重大区别吗?
在下面的例子中,由于主线程没有得到子线程的通知,它应该永远等待。但是主线程正在执行,下面示例的输出是:
c
l
total: 19900
Run Code Online (Sandbox Code Playgroud)
为什么主线程被执行?
c
l
total: 19900
Run Code Online (Sandbox Code Playgroud) 我正在创建一个任务轮询器,它每分钟查找一次任务。它看起来像这样:
public class Poller {
private final ExecutorService e = Executors.newSingleThreadExecutor();
public void start() {
e.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
final Task task = manager.getTask();
if (task != null) {
// ...
} else {
try {
TimeUnit.MINUTES.sleep(1);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
});
}
public void stop() {
e.shutdownNow();
}
}
Run Code Online (Sandbox Code Playgroud)
当我想停止轮询进程时,我执行stop(). 这会触发正在运行的线程上的中断,这将停止轮询器。
这工作正常。但是,我想知道该线程是否有可能被其他人(很可能是 JVM)中断。在这种情况下,轮询器将退出而不应该退出。
我知道我们可能会有虚假的唤醒,所以我们必须wait()用 a来保护awhile (condition) { ... }而不是if (condition) { ... } …
我有情景:我想等,直到某些事情是假的.通常需要20秒左右.
while(foo) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
或者就这样去?
while(foo) {
}
Run Code Online (Sandbox Code Playgroud)