在下面的代码中,如果我在 for 循环内使用 sysout 语句,则代码将执行并在满足条件后进入循环内部,但如果我不在循环内使用 sysout 语句,则无限循环将继续进行,而不会进入 if 条件,即使if 条件满足..任何人都可以帮我找出确切的原因。只需一条 sysout 语句即可使 if 条件变为 true。为什么会这样呢?
代码如下:-
class RunnableDemo implements Runnable {
private Thread t;
private String threadName;
RunnableDemo( String name){
threadName = name;
System.out.println("Creating " + threadName );
}
public void run() {
System.out.println("Running " + threadName );
for(;;)
{
//Output 1: without this sysout statement.
//Output 2: After uncommenting this sysout statement
//System.out.println(Thread.currentThread().isInterrupted());
if(TestThread.i>3)
{
try {
for(int j = 4; j > 0; j--) {
System.out.println("Thread: " + threadName + ", " + j);
}
} catch (Exception e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
}
}
public void start ()
{
System.out.println("Starting " + threadName );
if (t == null)
{
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
static int i=0;
public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo( "Thread-1");
R1.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i+=4;
System.out.println(i);
}
}
无限循环中没有 sysout 语句的输出:-
在无限循环中使用 sysout 语句输出:-
这里的问题可以通过改变来解决
static int i=0;
to
static volatile int i=0;
制作一个变量volatile
会产生许多复杂的后果,而我不是这方面的专家。因此,我将尝试解释我的想法。
变量i
存在于你的主内存(RAM)中。但 RAM 速度很慢,因此您的处理器将其复制到更快(且更小)的内存:缓存。事实上有多个缓存,但这无关紧要。
但是,当两个不同处理器上的两个线程将它们的值放入不同的缓存时,当值发生变化时会发生什么?那么,如果线程 1 更改了缓存 1 中的值,线程 2 仍然使用缓存 2 中的旧值。除非我们告诉两个线程该变量i
随时都可能发生变化,就像变魔术一样。这就是 volatile 关键字的作用。
那么为什么它与 print 语句一起工作呢?嗯,打印语句调用了很多幕后代码。其中一些代码很可能包含同步块或另一个易失性变量,它们(意外地)也会刷新i
在两个缓存中。 (感谢 Marco13 指出了这一点)。
下次您尝试访问时i
,你就得到了更新后的值!
PS:我在这里说的是 RAM,但它可能是两个线程之间最接近的共享内存,例如,如果它们是超线程的话,它可能是缓存。
这也是一个很好的解释(带图片!):
http://tutorials.jenkov.com/java-concurrency/volatile.html http://tutorials.jenkov.com/java-concurrency/volatile.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)