原子性
定义:
原子是世界上的最小单位,具有不可分割性。比如 i=1,这个操作是不可分割的,那么我们说这个操作是原子操作。再比如:i++,这个操作实际是i= i + 1,包括读取i,i+1,将结果写入内存 三个操作,是可以分割的,所以他不是一个原子操作。非原子操作都会存在线程安全问题,需要我们使用相关技术(比如sychronized)让它变成一个原子操作。一个操作是原子操作,那么我们称它具有原子性。
这句话的丰富含义有:
1.原子操作是对于多线程而言的,对于单一线程,无所谓原子性。
2.原子操作是针对共享变量的。
3.原子操作是不可分割的。指访问某个共享变量的操作从其他任意线程来看是不可分割的。
保证多线程原子性的方式:
1. 加锁
使用synchronized同步代码块保证线程的同步,从而保证多线程的原子性,但是加锁的话,就会使开销比较大。加锁和解锁是有消耗的。并且只要有加锁、解锁就会伴随着线程阻塞、线程唤醒,这样线程的切换也是消耗性能的。加锁本质上是将并发转变为串行来实现的,势必会影响吞吐量。
2. CAS无锁算法
CAS (比较与交换,Compare and swap)是一种有名的无锁算法, 即不使用锁的情况下实现多线程之间的变量同步。
CAS包含 3 个参数:共享变量的原始值A、预期值B和新值 C。只有当A的值等于B,才能把A的值变成C。也就是说预期值B等于原始值A,说明共享变量没有被其他线程修改过,所以才允许更新新值,这样就保证了原子性!如果A不等于B,说明共享变量已经被其他线程修改过了,当前线程可以放弃此操作。
基于这样的算法,CAS算法即使没有锁,也可以发现其他线程对当前线程的干扰,并进行恰当的处理。