线程安全之CAS
一、线程安全
-
线程概述
线程是程序执行的最小单位,是操作系统调度的基本单位。一个进程可以包含多个线程,每个线程独立执行,拥有自己的程序计数器、栈和局部变量等。
-
线程安全问题
线程安全问题指的是在多线程环境下,对共享资源的访问和操作而导致数据的不一致或不正确的结果。在多线程编程中,由于线程的并发执行,多个线程可能同时访问和修改共享的数据,如果没有合适的同步机制,就会出现竞态条件(Race Condition)和数据冲突等问题。
二、解决方案
- 第一种方案为给操作加上synchronized同步锁,这样一来,多个线程不可能会同时访问该操作,一定是一个线程先执行完成,另一个再进去执行,数据将不会出现不一致的问题,所以线程将是安全的。
- 而synchronized有一个缺点就是会降低性能,synchronized关键字会让没有得到锁资源的线程进入Blocked状态,而在得到锁的资源时恢复为Runnable状态,这个过程涉及到操作系统用户模式和内核模式的切换,代价比较高,那么还有没有其他解决方案可以保证线程安全呢?
- 第二种解决方案就是接下来要讲的CAS。
三、CAS
-
什么是CAS
CAS全称为Compare And Swap,即比较并交换。
-
CAS原理
其中V表示要更新的变量,E表示预期值,N表示新值。对变量V执行CAS操作,如果V等于预期值E,说明该变量没有被其他线程修改过,就将V的值更新为N;如果V的值不等于预期值E,则说明该变量被其他线程进行更改过了,所以不进行更新操作,接下来就是重新读取V值进行CAS操作再次尝试更新变量。
-
CAS的缺点
- CPU开销过大:在并发量比较高的情况下,如果许多线程反复尝试去更新一个变量,却又一直更新失败,循环往复,会消耗CPU很多资源
- ABA问题:CAS会导致“ABA问题”。简单来说,CAS就是取出当前值与预期值进行比较然后替换,但是可能会存在一个时间差,比如线程A从内存位置中取出变量a,这时候线程B也从中取出变量a,线程B在线程A进行CAS的比较操作前将变量a改为b然后再改为a,此时线程A的CAS比较操作不能判断出变量a是否被更改过,因为和读取的值一样,所以会更新成功。(一种解决方法为多比较一个版本号)
- 不能保证代码块的原子性:CAS机制保证的是单个变量的原子性操作,若要保证多个变量的原子性操作,可以封装在一起,但是这样得不偿失,开销太大,还不如直接采用synchronized同步锁