所谓原子性操做,指执行一系列操做时,这些操做要么所有执行,要么所有不执行,不存在只执行其中一部分的状况。
计数器状况:通常在设计计数器的时候都是先读取当前值,而后 +1,最后更新。真个过程是读-改-写的过程,若是不能保证该过程的原子性,那么就会出现线程安全问题。以下代码就不能保证 ++a 是原子性操做。java
public class ThreadNotSafeCount { private int a; public int getA() { return a; } public void increase() { ++ a; } }
如何保证多个操做的原子性?最简单方法是使用 synchronized 关键字进行同步,代码以下:安全
public class ThreadNotSafeCount { private int a; public synchronized int getA() { return a; } public synchronized void increase() { ++ a; } }
分析:使用 synchronized 关键字能够实现线程安全性,即内存可见性和原子性。但 synchronized 是独占锁,即没有获取内部锁的线程会被阻塞,而这里的 getA 方法只是读操做,多个线程同时调用不会存在线程安全问题,加入 synchronized 关键字,形成同一时间只能有一个线程对其进行调用,大大下降了并发性。为了保证共享变量 a 的内存可见性,还得须要 synchronized 来实现内存可见性。这样一来一边下降了并发性,一方面还必需要使用保证内存可见性,因此须要一种方式能够不下降并发性,并且能够保证内存可见性。这样的方式是存在的,这就是 CAS 操做。并发