Java中自增自减的线程安全问题

 package com.hq;
public class SafeThreadTest extends Thread {
 private JavaPlusTest jpt;
 public SafeThreadTest(ThreadGroup tg,JavaPlusTest jpt){
  this.jpt=jpt;
 }
 public void run(){
  jpt.countPlus();
  try {
   sleep(10);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

--线程类

 package com.hq;
import java.util.concurrent.atomic.AtomicInteger;
public  class JavaPlusTest {
 private Integer i=new Integer(0);
 //private AtomicInteger i=new AtomicInteger(0);
 public JavaPlusTest() {
  // TODO Auto-generated constructor stub
 }
 public Integer getI() {
  return i;
 }
 public void setI(Integer i) {
  this.i = i;
 }
 public void countPlus(){
  synchronized(i){i++;}
 }
 public static void main(String args[]){
  JavaPlusTest jpt=new JavaPlusTest();
  ThreadGroup tg=new ThreadGroup("group");
  SafeThreadTest stt=new SafeThreadTest(tg,jpt);
  for(int a=1;a<=10;a++){
   new Thread(tg,stt).start();;
   System.out.println("a="+a+" i="+jpt.getI());
  }
  while(tg.activeCount()>0){
   
  }
  System.out.println(jpt.getI());
 }
}

运行结果为a=1 i=0
a=2 i=0
a=3 i=0
a=4 i=0
a=5 i=2
a=6 i=4
a=7 i=4
a=8 i=4
a=9 i=5
a=10 i=6
10

如果把其中的

 public void countPlus(){
  synchronized(i){i++;}
 }

中的对象锁 synchronized(i)去掉改为

  public void countPlus(){
      i++;
 }

多运行几次,会发现有可能出现以下结果

a=1 i=0
a=2 i=0
a=3 i=0
a=4 i=0
a=5 i=0
a=6 i=2
a=7 i=3
a=8 i=5
a=9 i=6
a=10 i=6
9

猜想:两个线程同时进入countPlus()方法时,JVM将i++这句代码分为 获取i的原值并且+1和将运算后的值赋给i 两步,当线程A进入countPlus()时 将获取运算后的值i+1 时,尚未赋值给i,此时线程B也进入该方法,并且获取尚未赋值的i。这样运算后,就会出现少加或者少减的情况。而AtomicInteger是原子操作,从源代码看,其中使用了volatile

 private volatile int value;

因而不会出现线程不安全的问题。

你可能感兴趣的:(Java中自增自减的线程安全问题)