【发布时间】:2017-08-27 23:26:25
【问题描述】:
所以,在一些工作面试之后,我想编写一个小程序来检查 i++ 在 java 中是否真的是非原子的,并且在实践中应该添加一些锁定来保护它。事实证明你应该这样做,但这不是这里的问题。
所以我在这里写了这个程序只是为了检查它。
问题是,它挂了。似乎主线程卡在t1.join()
行,即使两个工作线程都应该因为上一行的stop = true 而完成。
我发现悬挂停止如果:
- 我在工作线程中添加了一些打印(如在 cmets 中),可能导致工作线程有时放弃 CPU 或
- 如果我将标志
boolean stop标记为volatile,导致立即写入 被工作线程看到,或者 - 如果我将计数器标记为
tasvolatile... 我不知道是什么原因导致未挂起。
有人可以解释发生了什么吗?为什么我会看到挂起,为什么在这三种情况下它会停止?
public class Test {
static /* volatile */ long t = 0;
static long[] counters = new long[2];
static /* volatile */ boolean stop = false;
static Object o = new Object();
public static void main(String[] args)
{
Thread t1 = createThread(0);
Thread t2 = createThread(1);
t1.start();
t2.start();
Thread.sleep(1000);
stop = true;
t1.join();
t2.join();
System.out.println("counter : " + t + " counters : " + counters[0] + ", " + counters[1] + " (sum : " + (counters[0] + counters[1]) + ")");
}
private static Thread createThread(final int i)
{
Thread thread = new Thread() {
public void run() {
while (!stop)
{
// synchronized (o) {
t++;
// }
// if (counters[i] % 1000000 == 0)
// {
// System.out.println(i + ")" + counters[i]);
// }
counters[i]++;
}
};
};
return thread;
}
}
【问题讨论】:
标签: java multithreading volatile