为什么这个坏程序总是运行? [英] Why this broken program always runs?
问题描述
我正在尝试使用JCIP中的示例,但以下程序不应运行,但是即使我执行它说20次也可以正常工作,这意味着ready
和number
在这种情况下也变得可见
I was trying examples from JCIP and Below program should not work but even if I execute it say 20 times it always work which means ready
and number
are becoming visible even if it should in this case
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread implements Runnable {
public void run() {
while (!ready)
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().availableProcessors());
//Number of Processor is 4 so 4+1 threads
new Thread(new ReaderThread()).start();
new Thread(new ReaderThread()).start();
new Thread(new ReaderThread()).start();
new Thread(new ReaderThread()).start();
new Thread(new ReaderThread()).start();
number = 42;
ready = true;
}
}
在我的机器上,它总是打印
On my machine it always prints
4 -- Number of Processors
42
42
42
42
42
According to Listing 3.1 of JCIP It should sometimes print 0 or should never terminate it also suggest that there is no gaurantee that ready and number written by main thread will be visible to reader thread
更新 在使所有线程仍保持相同的输出后,我在主线程中添加了1000ms睡眠.我知道程序已损坏,我希望它的行为如此
Update I added 1000ms sleep in main thread after strating all threads still same output.I know program is broken And I expect it behave that way
推荐答案
此程序已损坏,因为ready
和number
应该声明为volatile
.
由于ready
和number
是原始变量,因此对它们的操作是原子性的,但是但不能保证确保它们在其他线程中可见.
似乎调度程序在之后 main
之后运行线程,这就是为什么他们看到number
和ready
被初始化的原因.但这只是一个调度.
如果您添加例如main
中的sleep
以影响调度程序,您将看到不同的结果.
因此,本书是正确的,因为不能将变量未声明为volatile
,所以不能保证在单独线程中运行的Runnable
是否会看到变量的更新.
This program is broken since ready
and number
should be declared as volatile
.
Due to the fact that ready
and number
are primitive variables, operations on them are atomic but it is not guaranteed that they will be visible by other threads.
It seems that the scheduler runs the threads after main
and that is why they see the number
and ready
being initialized. But that is just one scheduling.
If you add e.g. a sleep
in main
so as to affect the scheduler you will see different results.
So the book is correct, there is no guarantee whether the Runnable
s running in separate threads will ever see the variable's being updated since the variables are not declared as volatile
.
更新:
这里的问题是,由于缺少volatile
,编译器可以自由读取字段ready
一次,并在每次循环执行中重用缓存的值.
该程序具有固有的缺陷.由于线程问题,通常在将应用程序部署到现场时会出现问题.
来自 JSL :>
Update:
The problem here is that the due to the lack of volatile
the compiler is free to read the field ready
just once, and reuse the cached value in each execution of the loop.
The program is inherently flawed. And with threading issues the problem usually appears when you deploy your application to the field....
From JSL:
例如,在下面的(破碎)代码片段中,假定 this.done是一个非易失性布尔字段:
For example, in the following (broken) code fragment, assume that this.done is a non-volatile boolean field:
同时(!this.done)
Thread.sleep(1000);
while (!this.done)
Thread.sleep(1000);
编译器可以自由读取一次this.done字段,然后重用 每次执行循环时的缓存值.这意味着 即使其他线程更改了该循环,循环也永远不会终止 this.done的值.
The compiler is free to read the field this.done just once, and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate, even if an other thread changed the value of this.done.
这篇关于为什么这个坏程序总是运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!