Java基础-a++/a--

Java基础-a++/a--

1. a++/a--

 

2. 自增自减是包含两个两个操作,不是线程安全的

  自增、自减运算符本质上不是一个计算操作,而是两个计算操作。以a++为例,这个运算将会编译器解析成:a=a+1,即包含两个单目运算符(+、=),一个单目运算符的计算操作可以看作是一个原子性操作。a++的步骤可以描述成 :
  1、先取a加1,将结果存储在临时空间;
  2、将结果赋给a。所以,自增自减运算符包含两个操作:一个加1(减1)的操作和一个赋值的操作

  这个原理好像对我的编程没有用吧?不是的,在单线程的环境下,你可以不管这个细节。但在多线程的情况下,你就得时刻牢记这个细节了。要知道,自增自减不是原子性操作,也就是说不是线程安全的运算。因此,在多线程下,如果你要对共享变量实现自增自减操作,就要加锁,或者使用JDK提供的原子操作类(如AtomincIntegerAtomicLong等)提供的原子性自增自减方。

来看个例子,验证一下。下面的例子提供三个静态变量(一个是原子操作类),创建了10个线程,每个线程都对这三个变量以不同的方式进行加1操作,并循环1000次。

public class TestController {

static int a = 0;
static int b = 0;
//原子性操作类
static AtomicInteger atomicInt = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) { //创建10个线程
Thread t = new Thread() {
@Override
public void run() {
for (int j = 0; j < 1000; j++) {//计算1000次
a = a + 1;
b++;
atomicInt.incrementAndGet();//自增的原子性方法
}
}
};
t.start();
}
// 判断当前的活动线程是不是只有main线程,以确保10个计算线程执行完成。
while (Thread.activeCount() > 1) {
Thread.sleep(1000);
}
System.out.println("a=a+1在多线程下的结果是:" + a);
System.out.println("b++在多线程下的结果是:" + b);
System.out.println("原子操作类AtomicInteger在多线程下的结果是:" + atomicInt.get());
}
}

运行结果:

a=a+1在多线程下的结果是:8883
b++在多线程下的结果是:8974
原子操作类AtomicInteger在多线程下的结果是:10000

  从运行的结果可以看出,a=a+1、b++不是线程安全的,没有计算出正确的结果10000。也就是说这两个表达式都不是原子性操作。事实上,它们都包含了两个计算操作。

 

posted on 2020-03-30 10:45  寂寞一沙洲  阅读(595)  评论(0编辑  收藏  举报

导航