可见性(volatile)
在线程中,存在 主内存 和每个线程各自的 工作内存 ,线程运行时会把主内存中的拷贝过来并进行操作。
如果不加volatile关键字的话,在一个线程中修改后,其他线程是不可见的。
加了volatile关键字后,在一个线程中修改时会将主内存中的同时进行刷新,其他线程就可看见修改后的内容。
例:
可以看到给flag加了volatile关键字后,b线程将其修改后对a线程是可见的
原子性(Atomic)
指一个操作是不可中断的。操作要么全部执行,且执行过程中不被打断,要么不执行。
例:
虽然使用了volatile关键字使 x 为可见的,但是
由于x++
是非原子性的,所以程序运行结果错误
需要使用AtomicInteger
来保证 x 的原子性
AtomicInteger
是利用循环CAS实现原子性的
CAS
Compare And Swap
在改变值之前先比较值是否与改之前的值相同,如果相同,则将其改变。如果不同,说明值已经被其他线程改过,则不进行操作。
CAS会产生
- ABA问题:一个值A变成B以后又被改回到A(即 值 被别的线程动过)
解决ABA问题:加一个版本号
对值进行操作时需要同时满足两个条件:
(1)值相同
(2)版本号相同
-
时间开销大
CAS如果长时间不成功,会给CPU带来非常大的执行开销 -
只能保证一个共享变量的原子操作
JAVA线程原子类
1.基本数据类型
AtomicBoolean
AtomicInteger
AtomicLong
2.数组
AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
3.引用
AtomicReference
AtomicReferenceFiledUpdater
AtomicMarkableReference
4.字段
AtomicIntegerFiledUpdater
AtomicLongFiledUpdater
AtomicStampedReference
有序性(volatile)
程序执行的顺序按照代码的先后顺序执行。
在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。
可以使用 volatile 关键字来保证有序性