2014-10-26 127 views
2

我一直在阅读关于JSL中易失变量的部分。该规范提供了一个例子,我尝试着尝试一下。我写的代码:通过示例了解易失变量

static volatile int i = 0, j = 0; 

public static void main(String args[]) { 
    Thread t1 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      for (int k = 0; i < 200000; k++) { 
       i++; 
       j++; 
      } 
     } 
    }); 
    Thread t2 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      for (int k = 0; i < 200000; k++) { 
       System.out.println("i=" + i + " j=" + j); 
      } 
     } 
    }); 
    t1.start(); 
    t2.start(); 
} 

好吧,我预计j<=i(SPEC说),但事实并非如此:

i=147609 j=147684 
i=149412 j=149521 
i=150447 j=150523 
i=151384 j=151457 
i=152307 j=152380 
i=153222 j=153297 
i=154139 j=154214 
i=155065 j=155138 
i=155967 j=156040 
i=156880 j=156952 
i=157790 j=157863 
i=158760 j=158833 
i=159671 j=159747 
i=160592 j=160664 
i=161510 j=161584 
i=162420 j=162497 
i=163350 j=163425 
i=164292 j=164365 
i=165230 j=165306 
i=166179 j=166252 
i=167113 j=167187 
i=168055 j=168128 
i=169002 j=169078 
i=169948 j=170021 
i=170898 j=170974 
i=171851 j=171924 
i=172794 j=172866 
i=173724 j=173796 
i=174658 j=174733 
i=175641 j=175714 
i=176572 j=176645 
i=177503 j=177575 
i=178442 j=178517 
i=179394 j=179467 
i=180328 j=180403 
i=181276 j=181351 
i=182232 j=182305 
i=183178 j=183251 
i=184130 j=184205 
i=185092 j=185167 
i=186043 j=186118 
i=186998 j=187071 
i=195792 j=195866 
i=196718 j=196784 
i=197629 j=197698 
i=198543 j=198608 
i=199489 j=199555 

有什么不对?

+2

引用来自您链接到的页面:但是,有可能的是,方法2的任何给定调用可能会观察到j的值远远大于为i观察到的值,因为方法一可能会执行多次在方法2获取i的值和方法2获取j的值的那一刻之间。*因此,不,spec没有“说那个”。 – 2014-10-26 17:13:50

回答

3

i的实际值将始终大于或等于j

您在日志中看到什么是实际(电流)ij值。在评估时,它的值为ij

你的链接文件指出

这是可能的,但是,这两个方法的任何给定调用可能 观察对于j值比为 我观察到的价值要大得多,因为方法一个可能当方法二取得i的值和方法二取得j的值时的时刻 之间执行多次。

主题t1运行,增加ij一堆倍。上下文切换。线程t2运行,评估i并连接它。上下文切换。线程t1继续递增ij。上下文切换。线程t2评估j并连接它。所以j仍然小于或等于i,你只是在不同的时间评估它们。