1.CopyOnWrite
写少读多的场景
读-读 读-写 写-读 不阻塞
写-写阻塞
写时复制,为什么复制?为了迭代器等遍历读操作的安全与性能,同String
set中看似比较多余的一句,背后的目的是什么,涉及到happens-before,多线程下volatile防止指令重排,确保可见性
数据读,总量读,迭代器符合最终一致性
2.ConcurrentLinkedQueue
无界,线程安全的LinkedList
基于CAS
tail最终一致
size最终一致
3.BlockingQueue
无界:LinkedBlockingQueue,有界:ArrayBlockingQuere
线程池默认四种类型用无界阻塞队列
基于重入锁
两种BQ有何区别
size强一致
产生最终一致的根本原因是:
写不阻塞读,读时不加锁,也没用volatile确保一个线程(节点)的写入立即对其它线程(节点)的读可见(concurrenthashmap是典型案例), 即失去线程间的可见性,读给历史版本(比如CLQ的size,Mysql的MVCC),或者根本是两样东西(CopyOnWrite)
写的东西非volatile(ConcurrentHashMap 的get和迭代器)