synchronized 悲观 阻塞式,冲突多, 先锁后更新
原子变量 乐观 非阻塞,冲突少, CAS更新(冲突检测=>冲突,继续尝试)
性能synchronized<原子变量
乐观
原子变量 简单
复杂如下:
ConcurrentLinkedQueue和ConcurrentLinkedDeque:非阻塞并发队列
ConcurrentSkipListMap和ConcurrentSkipListSet:非阻塞并发Map和Set
synchronized锁相比,这种原子更新方式代表一种不同的思维方式。
synchronized是悲观的,它假定更新很可能冲突,所以先获取锁,得到锁后才更新。原子变量的更新逻辑是乐观的,它假定冲突比较少,但使用CAS更新,也就是进行冲突检测,如果确实冲突了,那也没关系,继续尝试就好了。
synchronized代表一种阻塞式算法,得不到锁的时候,进入锁等待队列,等待其他线程唤醒,有上下文切换开销。原子变量的更新逻辑是非阻塞式的,更新冲突的时候,它就重试,不会阻塞,不会有上下文切换开销。
对于大部分比较简单的操作,无论是在低并发还是高并发情况下,这种乐观非阻塞方式的性能都要远高于悲观阻塞式方式。
原子变量是比较简单的,但对于复杂一些的数据结构和算法,非阻塞方式往往难于实现和理解,幸运的是,Java并发包中已经提供了一些非阻塞容器,我们只需要会使用就可以了,比如:
ConcurrentLinkedQueue和ConcurrentLinkedDeque:非阻塞并发队列
ConcurrentSkipListMap和ConcurrentSkipListSet:非阻塞并发Map和Set