由于system.out.println语句而导致运行线程延迟

Mee*_*ari 5 java multithreading interrupt

在下面的代码中,如果我在for循环中使用sysout语句然后代码执行并在条件满足后进入循环内部但如果我不在循环内使用sysout语句然后无限循环继续进行而不进入if条件内部即使如果条件满足..任何人都可以请帮助我找出确切的原因.只是一个sysout语句使if条件成为真.为什么会这样?

代码如下: -

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);
   }   
}
Run Code Online (Sandbox Code Playgroud)

无限循环中没有sysout语句的输出: - 在此处输入图像描述

在无限循环中使用sysout语句输出: - 在此输入图像描述

Hen*_*oer 3

这里的问题可以通过改变来解决

static int i=0;

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