本章主要内容:无锁保证多线程安全,这里的无锁是乐观锁的一种,具体采用 CAS+volatile 实现

无锁多线程并发具体使用:

  • 共享变量改成原子类型,如原子变量/原子引用
  • 方法中对共享变量的访问均由CAS保证了其原子性

线程安全问题,本质就是多线程对共享变量访问的非原子性,所以原子变量/原子引用从根本上保证了线程安全。

关于CAS一些概念的纠正:

1、CAS是原子操作

这里实际指的是compareAndSet这个方法是原子操作,而CAS整个代码不是原子的,因为还是会随着线程切换而发生指令切换。某个方法是原子的,但多个方法组合不是原子的。

  1. public void withdraw(Integer amout) {
  2. while(true){
  3. int prev=balance.get();//获取balance的最新值
  4. //要修改后的余额
  5. int next=prev-amout;
  6. //真正修改
  7. if(balance.compareAndSet(prev,next)){
  8. break;
  9. }//修改前和修改后的值传入
  10. }
  11. }

2、CAS能够保证线程安全

线程安全问题引发的根本,是多线程对共享变量“又读又写”的指令发生了交错。

一般意义上的线程安全是指synchronized块使得整块代码都保证原子性,从而使得根本不会发生指令交错。
但CAS无法保证整体原子性,只能保证compareAndSet方法是原子的,保证线程安全的手段实际是把读的部分放入了compareAndSet方法中,交由compareAndSet方法实现线程安全,这样即使多线程访问代码出现指令交错,并不会出现读写指令交错的情况。

3、线程安全≠原子性

线程安全实际是指多线程访问共享变量,最终结果正确即可,其并不只有原子性(synchronized加锁)一种方法实现。