日期:2014-05-20  浏览次数:20759 次

java “number++” 的原子性操作问题。
问各位一个问题:

例如:

  private static int number=0;

  public static void add(){
  number++;
  }

  private static final int MAX_COUNT=10;
   
  public static void main(String [] args){
  Thread [] threads=new Thread[MAX_COUNT];
  for(Thread t:threads){
  t=new Thread(new Runnable() {
public void run() {
for(int i=0;i<100;i++){
add();
}
}
});
  t.start();
  }
 
  while(Thread.activeCount()>1)Thread.yield();
 
  System.out.println(number);
  }

由于没有使用同步 所以在同时运行add()方法的线程可能会不止一个,
然则number++的操作并非原子操作: 
在使用javap 之后看到其对应的指令为:


  //静态成员number压入操作数堆栈
  0: getstatic #13 // Field number:I
  //创建一个临时变量
  3: iconst_1
  4: iadd
  //静态成员number出栈放到常量解析池
  5: putstatic #13 // Field number:I
 


由此我的看法是 “number++” 有四条指令,一定不会是一个原子性操作(一条指令都未必是原子性操作...)

一个方法中多个线程都在操作,并且没法保证修改变量操作的原子性.那么为什么每次都还能得到正确的值呢?
莫非是编译时候有过优化?





------解决方案--------------------
不是每次都能得到正确的值的!也许你进行了多次尝试还是得到同一个结果,主要是一个线程的加法操作只进行了一百次。你把循环次数弄到10000就可以看到明显的结果差异了。原因:新的线程创建完成前,100次的加法操作已经完成了。但不是每次都可以,可能在进行加法的时候该线程失去了控制权,这时你就有可能看到其他结果。