[英]Spurious wakeups on windows. Is it possible?
I recently learned "Spurious wakeups" Any people say that this problem possible only for some types of Linux PC. 我最近学到了“虚假唤醒”任何人都说这个问题只适用于某些类型的Linux PC。
I use windows. 我用的是Windows。
I wrote test for Spurious wakeups. 我写了Spurious唤醒测试。 I got result that it is possible.
我得到的结果是可能的。 But I want to show this test for you.
但我想为你展示这个测试。 Maybe I made mistake somewhere.
也许我在某处弄错了。
my initial variant: 我最初的变种:
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class TestSpuriousWakeups {
static final int MAX_THREADS = 600;
static final Object mutex = new Object();
static final CountDownLatch allThreadsStarted =
new CountDownLatch(MAX_THREADS);
static final CountDownLatch allThreadsFinished =
new CountDownLatch(1);
static /*final*/ volatile AtomicInteger processedThreads = new AtomicInteger();
static /*final*/ volatile AtomicInteger notifiedThreads = new AtomicInteger();
final int n = 10;
static volatile boolean continueCondition = true;
static final Random sleepRandom = new Random();
static class Worker extends Thread {
public void run() {
try {
synchronized (mutex) {
allThreadsStarted.countDown();
mutex.wait();
}
continueCondition = true;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
processedThreads.incrementAndGet();
}
}
}
static class Notifier extends Thread {
public void run() {
while (true) {
if (processedThreads.get() == MAX_THREADS)
break;
synchronized (mutex) {
doStuff();
mutex.notify();
continueCondition = false;
notifiedThreads.incrementAndGet();
}
}
allThreadsFinished.countDown();
}
// just to emulate some activity
void doStuff() {
try { Thread.sleep(sleepRandom.nextInt(5)); }
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < MAX_THREADS; i++)
new Worker().start();
// wait for all workers to start execution
allThreadsStarted.await();
new Notifier().start();
// wait for all workers and notifier to finish execution
allThreadsFinished.await();
System.out.println("Spurious wakeups count: "
+ (MAX_THREADS - notifiedThreads.get()));
}
}
4 random execution: 4随机执行:
Spurious wakeups count: -20
Spurious wakeups count: -5
Spurious wakeups count: 0
Spurious wakeups count: -407
So different values is wondering for me. 所以不同的价值观让我感到疑惑。
I added pair of rows to run method: 我添加了一对行来运行方法:
static class Notifier extends Thread {
public void run() {
while (true) {
while (!continueCondition) //added string
doStuff(); //added string
// all threads finished their execution
if (processedThreads.get() == MAX_THREADS)
break;
synchronized (mutex) {
doStuff();
mutex.notify();
continueCondition = false;
notifiedThreads.incrementAndGet();
}
}
allThreadsFinished.countDown();
}
after it I cannot get something another than 在它之后,我不能得到别的东西
Spurious wakeups count: 0
Is it really Spurious wakeups or bug in my experiment ? 我的实验真的是虚假的唤醒或错误吗?
PS PS
I noticed that I see negatives numbers. 我注意到我看到负数。 Thus obviously it is experiment bug.
因此显然它是实验bug。 But I don't understand cause.
但我不明白原因。
Two things 两件事情
The race is between the exit of the synchronized block in your worker threads and when they reach processedThreads.incrementAndGet(). 竞争是在工作线程中同步块的退出与它们到达processedThreads.incrementAndGet()之间。 Notifier will spin during that time, notifying threads which may or may not have acquired the lock.
通知程序将在此期间旋转,通知可能已获取或未获得锁定的线程。
In other words 换一种说法
Your two added lines change the output because, by slowing down the Notifier, you're masking the race. 你添加的两行会改变输出,因为通过减慢通知程序,你就会掩盖比赛。 (By giving Worker lots of time to enter the mutex.)
(通过给工人很多时间进入互斥锁。)
Hope that makes some sense. 希望这有点道理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.