今天做了个线程的小列子,代码如下
public class Test
{
    private  int x; 
    public void foo()
       { 
 int current=x;
       x=current+1; 
       }
    public void go()
       {
  for(int i=0;i<3;i++)
           {
  new Thread(){
    public void run(){
    foo();
       System.out.println(x);
     }
   }.start();
           }
       }  
       public static void main(String[] str)
       {
           new Test().go();
        }
}有时会输出
2 3  2
  
我感觉很奇怪,想不明白其中的道理,按我自己的分析,应该是这样的...调用go()方法后会启动三个线程,三个线程都会调用foo()这个方法,foo()这个方法主要就是改变成员变量x的值,然后打印出x的值,显然,这三个线程是异步的,但是它们访问的x都是同一个成员变量呀,对于2,3,2这样的输出,按我的分析应该是这样的,首先运行的线程使x加1后就阻塞了,然后第二个线程运行时看到x已经等于1了就再加一等于2,然后其中一个阻塞,另一个打印,因为打印的都是同一个成员变量所以应该是修改后的值2没什么问题,然后第三个线程又改变x的值并打印出3(第三个线程执行时前面阻塞的那个线程应该还在阻塞不然怎么会打印3),然后阻塞的那个线程运行,按理说这时它要打印的x已经被第三个线程修改了成3了,为什么还输出2.我也考虑到了可能访问的是不同内存区的变量值,但在x前加上了 volatile 也没用呀十分困惑,请大家帮忙看看。我是哪里分析错了。为什么会打印出这样的结果

解决方案 »

  1.   

    public class Test
    {
      private int x;  
      public void foo()
      {  
    int current=x;
      x=current+1;  
      }
      public void go()
      {
    for(int i=0;i<3;i++)
      {
    new Thread(){
    public void run(){
    foo();
      System.out.println(x);
    }
    }.start();
      }
      }   
      public static void main(String[] str)
      {
      new Test().go();
      }
    }
      

  2.   

    System.out.println(x);显然不是一个原子操作,还可以分为更多更小的步骤,对应着许许多多条指令
      

  3.   

    问题 应该不是出现在 System.out.println(x); 这句吧,如果在这句上加锁也解决不了问题呀
      

  4.   

    System.out.println(x);是io操作是最易阻塞的步骤,出现你所描述的情况说明x=2的值作为值传递方式已经传入println方法内部,作为println的内部变量的值,这时被阻塞,直到最后被打印出来。
      

  5.   


    public class Test {    private int x;    public void foo() {
            int current = x;
            x = current + 1;
        }    public void go() {
            for (int i = 0; i < 3; i++) {
                new Thread() {                @Override
                    public void run() {
                        foo();
                        print();
                    }
                }.start();
            }
        }    synchronized public void print() {
            System.out.println(x);
        }    public static void main(String[] str) {
            new Test().go();
        }
    }
      

  6.   

    但是 如果在 System.out.println(x) 这句上加上锁以后 也同样会出现这样的结果呀....
     synchronized(this)
    {
     System.out.println(x);
    }
      

  7.   

     哦,对不起 确实问题出在
    System.ou.println(x);这句上,
    加锁后,最后结果就不会比前面的小了