java容器与并发笔记

HashMap和红黑树:
红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能;
它可以在O(log n)时间内做查找,插入和删除,其中n是树中元素的数目;
又叫做平衡二叉B树、对称二叉B树;用于实现关联数组;
(注意:B-树、B+树都不是二叉树,AVL和红黑树都是二叉树;AA树与红黑树类似,只是左孩子不能为红色;)
(平衡二叉树还有很多,比如替罪羊树,伸展树,k邻居树,带权平衡树,跳表,Treap树堆;)
http://dongxicheng.org/structure/red-black-tree/

HashMap有2个重要的参数影响性能:initial capacity和load factor;
capacity是hash table中buckets的个数,默认值为16;
load factor决定了hash table在多满时被扩容;
(代表一个链中平均存储的元素个数,可以大于、小于、等于1;)
扩容时需要再哈希,即内部数据结构发生变化;
load factor的默认值0.75能很好的平衡空间和时间的开销;
hash table的容量总是2的整数次幂;
扩容方法是resize,每次扩展到原先的2倍;(值得研究!)
get方法很简单,先对key进行hash找到数组下标,遍历链表找到该key;
put方法也是先找到下标,然后对key判重,如果没有重复,就插入到链表的表头;
好的哈希函数满足:计算简单、散列地址分布均匀;
(具体方法有:直接定址法、数字分析法、平方取中法、折叠法、除留余数法、随机数法;)
(HashMap的Node的hashCode方法重写了Object的方法,具体是Objects.hashCode(key) ^ Objects.hashCode(value);)
(hash方法才是HashMap真正的哈希函数,是对key的hashCode进行异或、移位得到的;)
HashMap采用链地址法(或叫拉链法)来解决哈希冲突;(别的方法还有:开放定址法、再散列法、建立公共溢出区;)
(其中开放定址法又分为线性探测再散列、二次探测再散列、伪随机探测再散列;)
https://www.cnblogs.com/chengxiao/p/6059914.html !!!
hashMap的数组长度保持2的次幂,是为了保证得到的新数组和老数组索引一致;
(大大减少已经散列良好的老数组的数据位置调换;即要么呆在原位,要么去下标为power of two offset的位置;比如16扩到32,下标1可以去下标1或下标17;)
(当长度为16,length-1就是15,即01111;当长度为32,length-1就是31,即011111;根据index=hash&(length-1)可知index和hash关系较为简单;)

jdk1.7是数组+链表,jdk1.8是数组+链表+红黑树,即把每个链表用红黑树代替(所以有多颗红黑树);
(链表的查找时间复杂度是O(n),而红黑树的查找时间复杂度是O(log n))

http://www.importnew.com/28263.html !!!

HashMap和TreeMap中,红黑树都是一个节点对应一条记录!

HashMap实现了KeyIterator、ValueIterator、HashIterator、EntryIterator等迭代器(都是内部类);

HashMap继承AbstractMap抽象类,而后者实现Map接口;
(一般都是接口-抽象类-具体类;)

java8以上HashMap用红黑树实现,那它和TreeMap啥区别?为啥不直接用TreeMap,而是重新基于TreeNode实现?
(HashMap是利用数组实现的,需要提前扩容,而TreeMap是真正意义上的树,在插入节点的时候挨个分配内存!)
(HashMap只在hash冲突多的时候由链表转为红黑树,不是全部用红黑树实现;(当链表元素超过8个以后,见TREEIFY_THRESHOLD变量))
(HashMap比TreeMap效率高,不管是插入、删除还是读取,因为TreeMap排过序(SortedMap接口),而HashMap是随机的;)

TreeNode和红黑树:
TreeNode是红黑树的节点结构类,还有一些方法;
(TreeNode类的rotateLeft、rotateRight是红黑树翻转方法;balanceDeletion、removeTreeNode是删除节点方法;balanceInsertion是插入节点方法;)
(TreeNode是一个LinkedHashMap.Entry,而后者是一个HashMap.Node,而HashMap.Node又是一个Map.Entry;其中Node有hash值、key、value和next等字段;)
(所以TreeNode是一个Node;且TreeNode或Node都有哈希表的基本字段;一个节点存储一条Key-value记录;)
(注意:TreeNode比Node大了一倍,因为除了Node的基本字段,它还包括parent、left、right、prev、red字段;)

TreeMap和红黑树:
TreeMap继承AbstractMap,同时实现NavigableMap接口,而后者又继承SortedMap接口,而后者又继承Map接口;
TreeMap的内部类Entry代表一个红黑树的节点,有key、value、left、right、parent、color字段;
TreeMap类的rotateLeft、rotateRight是红黑树翻转方法;fixAfterInsertion、fixAfterDeletion、deleteEntry是插入和删除方法;
TreeMap不是以数组形式维护红黑树,而是只记录root节点,然后每个节点有left、right、parent节点,最终形成一棵树;
(这种方式需要每个节点都单独去分配内存?是的,可以看到put方法中,每次都要执行new Entry分配内存)
非线程安全,需要额外同步如Collections.synchronizedSortedMap;
简单说,TreeMap是纯粹用红黑树实现的!!!

TreeMap和TreeSet:
TreeSet是通过TreeMap实现的;(将NavigableMap作为成员变量;注意TreeMap也是一种NavigableMap;会new TreeMap)
非线程安全,需要额外同步如Collections.synchronizedSortedSet;
与HashSet类似,TreeSet也定义了Object对象(名为PRESENT),来充当TreeMap的value;

Map是java中的接口,Map.Entry是Map的一个内部接口;
https://www.cnblogs.com/heganlin/p/5914892.html
(一般Entry都是内部类或内部接口?)
(一个类的内部类可以是抽象类?如HashMap和HashIterator)

HashMap和ConcurrentHashMap:
ConcurrentHashMap的key、value都不能为null;
initial table capacity也是16,并且扩容后也是2的幂方;
默认load factor也是0.75;也是超过8个节点从链表变为红黑树;
内部类Node也是有hash、key、val、next字段;(只不过后两个字段加了volatile)
也有TreeNode类继承Node,并有parent、left、right、prev、red字段;
(TreeNode的findTreeNode方法是递归的;)
TreeBin类是红黑树的封装类,有读锁和写锁,有红黑树的各种操作,如旋转、插入、删除、查找;
TreeBin类被高层API,如replaceNode、clear、putVal等使用;
大量使用sun.misc.Unsafe类的方法;(有一个static变量Unsafe U)
table和nextTable数组一个是volatile,一个是transient volatile;
能不能说ConcurrentHashMap利用Unsafe类的CAS机制实现同步和线程安全?(如compareAndSwapObject方法)
内部类Traverser类有多个子类,如BaseIterator、KeySpliterator、ValueSpliterator、EntrySpliterator等;(advance方法是Traverser类的一个重要方法)
BaseIterator类又有多个子类,如KeyIterator、ValueIterator、EntryIterator;
Traverser类被高层API,如toString、equals、hashCode、containsValue等使用;
内部类BulkTask也有多个子类ForEachKeyTask、ForEachValueTask、ForEachEntryTask、ForEachMappingTask、ForEachTransformedValueTask、ForEachTransformedEntryTask、
ForEachTransformedMappingTask、SearchKeysTask、SearchValuesTask、SearchEntriesTask、SearchMappingsTask、ReduceKeysTask、ReduceValuesTask、
ReduceEntriesTask、MapReduceKeysTask、MapReduceValuesTask、MapReduceEntriesTask、MapReduceMappingsTask、MapReduceKeysToDoubleTask、
MapReduceValuesToDoubleTask、MapReduceEntriesToDoubleTask、MapReduceMappingsToDoubleTask、MapReduceKeysToLongTask、MapReduceValuesToLongTask、
MapReduceEntriesToLongTask、MapReduceMappingsToLongTask、MapReduceKeysToIntTask、MapReduceValuesToIntTask、MapReduceEntriesToIntTask、MapReduceMappingsToIntTask;
ForwardingNode节点和ReservationNode节点,和TreeNode类似,但作用不一样;
(ForwardingNode是正在被迁移的Node;)
ConcurrentHashMap最难的是扩容操作和迁移操作,即tryPresize方法和transfer方法,扩容后需要迁移,还有别的地方也会调用,如put、helpTransfer;
http://www.importnew.com/28263.html !!!
ConcurrentHashMap一定不会抛出ConcurrentModificationException;

如何理解jdk1.7的ConcurrentHashMap Segment,即分段锁?
concurrencyLevel可以理解为并发度、Segment数,默认有16个Segment,即同时支持16个线程并发写;(jdk1.8也有concurrencyLevel,见构造函数)
(注意,一旦初始化完成,不允许扩容;)
每个Segment对应一个哈希表,即和HashMap类似的结构,只是多了线程安全;
(这是可以扩容的;)
initialCapacity和loadFactor需要分配给每个Segment内部哈希表使用;

synchronized+HashMap什么时候不能代替ConcurrentHashMap?
Hashtable什么时候不能代替ConcurrentHashMap?
https://blog.youkuaiyun.com/sinbadfreedom/article/details/80467253 !!!

为啥jdk1.7中ConcurrentHashMap采用ReentrantLock实现同步,到jdk1.8又退回到用synchronized实现呢(当然还有Unsafe类的CAS机制)?
(与之鲜明对比是,CopyOnWriteArrayList只用ReentrantLock,而不用synchronized)

HashMap和ConcurrentHashMap在remove节点数变少,会导致红黑树转为链表吗?会,对应untreeify方法!
会自动缩容吗,缩小table数组?不会

ConcurrentHashMap和Hashtable:
并发度不一样;加锁范围不一样;
前者是node[]数组的依次遍历node[i]加的锁,node[i]可以是链表也可以是红黑树;
(获取头节点的锁,即synchronized (f);判断头节点hash值是否大于0,得知是否链表;或者用f instanceof TreeBin判断是否红黑树;)
后者是对整个Hashtable对象加锁(比table数组对象的锁范围还大!)

为啥没有ConcurrentHashSet?
因为可以通过ConcurrentHashMap.newKeySet()直接得到相应的Set,返回的是KeySetView类;
(另外一种方法是,Collections.newSetFromMap())
(没有WeakHashSet、IdentityHashSet同理!)

HashMap和Hashtable:
Hashtable继承Dictionary,而不是AbstractMap;(注意Dictionary已经被废弃,应使用Map;)
也是用table数组维护哈希表;load factor默认值也是0.75;initial capacity是11,扩容后为2n+1?
哈希函数不同,它是index = (hash & 0x7FFFFFFF) % tab.length;(所以不需要length是2的幂方?)
最大区别是各种方法加synchronized关键字,所以性能差一些;
Hashtable的key、value都不能为null;

Properties和Hashtable:
Properties是Hashtable的子类,通过synchronized实现线程安全;
(常用api有getProperty、setProperty、load、get等;)

HashMap和LinkedHashMap:
LinkedHashMap是有序的版本,它增加了时间和空间上的开销,通过维护一个运行于所有条目的双向链表,保证了元素迭代的顺序;
LinkedHashMap是HashMap的子类,可认为是HashMap+LinkedList,它使用LinkedList维护插入元素的先后顺序;
(意思是,LinkedHashMap会按照插入顺序打印,而HashMap会按照key的hashcode排序打印(因此相对插入顺序是乱序))
LinkedHashMap的内部类Entry是一个HashMap.Node,代表一个节点,同时有before, after字段,可见是一个双向链表;
LinkedHashMap的双向循环链表维护一个head和tail节点;
https://www.cnblogs.com/xiaoxi/p/6170590.html 可以很清楚看出LinkedHashMap的结构!
(只是在HashMap的结构上多了before, after指针,以及一个head和tail指针;)
简单说,LinkedHashMap是数组+双向循环链表!!!

HashMap是无序;LinkedHashMap是FIFO(按用户插入的顺序排);TreeMap是按键值的升序排序(也可以指定排序的比较器);
https://www.cnblogs.com/acm-bingzi/p/javaMap.html

HashMap和WeakHashMap:
和gc有关,当一个key不再被使用时,这个Entry节点会自动被移除;
(它的Entry节点继承了WeakReference类,)
也允许key或value为null;非线程安全,需使用Collections.synchronizedMap;也是2的幂方;
不依赖HashMap,而是自己实现所有基础API;

注意,没有WeekHashSet!但可以通过Collections.newSetFromMap包装得到;

HashMap和IdentityHashMap:
IdentityHashMap在判断key或value相等时比HashMap更严格,采用引用相等而不是值相等;(即k1==k2,而不是k1.equals(k2))
使用场景较少,在serialization or deep-copying以及proxy objects时使用;
也允许key或value为null;非线程安全,需使用Collections.synchronizedMap;也是2的幂方;
不依赖HashMap,而是自己实现所有基础API;(最大的区别是,不使用拉链法,而是用线性探测再散列(linear-probe)解决哈希冲突;所以不会有红黑树啦;)

HashMap和HashSet:
HashSet是通过HashMap实现的(将HashMap作为成员变量);允许value为null;
非线程安全,需要额外同步;或者用Collections.synchronizedSet;
非常有意思的是,HashSet定义了Object对象(名为PRESENT),来充当HashMap的value;

HashSet和LinkedHashSet:
LinkedHashSet是HashSet的子类,源码更少、更简单,唯一区别是LinkedHashSet内部使用的是LinkedHashMap;
或者说,LinkedHashSet直接使用LinkedHashMap实现;(但是相关代码在HashSet类中;事实上LinkedHashSet和HashSet两个都不干活,都分别依赖LinkedHashMap和HashMap)
也允许value为null;非线程安全,需要额外同步;或者用Collections.synchronizedSet;

ConcurrentSkipListMap、ConcurrentSkipListSet:
跳表在原有的有序链表上增加了多级索引,通过索引来实现快速查找;在搜索、插入、删除性能都有提高;(性能和红黑树,AVL树不相上下)
跳表的其他应用包括Redis、LeveIDB等;之所以用SkipList是因为,实现比AVL简单!思想是空间换时间、二分查找、概率均衡技术;
https://en.wikipedia.org/wiki/Skip_list
https://blog.youkuaiyun.com/sunxianghuang/article/details/52221913 !!!
ConcurrentSkipListMap的containsKey、get、put、remove的时间复杂度都是log(n);数据节点按照关键字升序排列;
内部类Node有key、value、next字段;内部类Index、HeadIndex;
注意,ConcurrentSkipListMap实现同步,既没有使用ReentrantLock,又没有使用synchronized,而是使用UNSAFE;
有序又线程安全用ConcurrentSkipListMap;有序非线程安全用TreeMap;(注意:jdk没有ConcurrentTreeMap)
ConcurrentSkipListSet基于ConcurrentSkipListMap实现(将它作为成员变量,事实上是ConcurrentNavigableMap);

CopyOnWriteArrayList和CopyOnWriteArraySet:
(为啥List和Set这里发生对比,而没有Map?因为在构造List的时候,可以通过确保元素唯一实现Set的逻辑)
(为啥没有CopyOnWriteLinkedList?以及CopyOnWriteLinkedSet?因为链表无法通过直接new得到吧)
CopyOnWriteArraySet基于CopyOnWriteArrayList实现(将它作为成员变量);也是线程安全的;也适用于读多写少的场景;
CopyOnWriteArraySet没有提供Set的逻辑,而是利用CopyOnWriteArrayList的如addIfAbsent方法来实现‘集合元素唯一性’;

目前已4种实现Set的方式:
基于哈希表实现的HashSet、LinkedHashSet;基于数组实现的CopyOnWriteArraySet;基于红黑树实现的TreeSet;基于跳表实现的ConcurrentSkipListSet;

五类线程安全性:不可变、线程安全、有条件线程安全、线程兼容和线程对立
(不可变的对象一定是线程安全的;如Integer 、 String都是;)
(线程安全或绝对线程安全,是任何时候都不需要额外同步,很少见)
(Hashtable或Vector都是相对线程安全或有条件线程安全,即它们在某些场景仍需要额外的同步,否则也会抛ConcurrentModificationException;)
(ArrayList和HashMap都属于线程兼容,即非线程安全;)
(线程对立是不管是否调用外部同步都不能在并发使用时安全地呈现的类。线程对立很少见)

以下说法正确的是:(ABDG)
A. CopyOnWriteArrayList不会抛出ConcurrentModificationException
B. ConcurrentHashMap不会抛出ConcurrentModificationException
C. Hashtable和Vector不会抛出ConcurrentModificationException
D. 写多读少时,CopyOnWriteArrayList性能不如synchronized的ArrayList
E. CopyOnWriteArrayList修改对线程立即可见
F. 线程安全的容器不会抛出ConcurrentModificationException
G. ConcurrentSkipListMap不会抛出ConcurrentModificationException

很多线程安全的容器也会抛ConcurrentModificationException,其实是它的迭代器iterator抛出的(比如Vector、Hashtable,当然非线程安全的ArrayList也是);
当迭代器检测到不一致的时候,就会抛出该异常;(事实上,当迭代器初始化后,jdk希望你用迭代器去remove、add等,而不是用其他方式去操作;)
但较新版本jdk(jdk1.5以后)的线程安全的容器,都不会抛出该异常,比如ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentSkipListMap等;
注意:不是线程安全的容器就一定不会抛出ConcurrentModificationException,比如Vector、Hashtable;
(只需要额外加synchronized同步即可!)
https://www.cnblogs.com/dolphin0520/p/3933551.html !!!

线程安全和ConcurrentModificationException没有必然关系!

Vector、ArrayList、LinkedList、CopyOnWriteArrayList:
Vector元素存放在Object[] elementData数组中;Vector和Hashtable类似,通过在各方法加synchronized关键字,实现线程安全;
Vector支持动态扩容和缩容?
ArrayList和Vector类似,只不过非线程安全,性能比Vector好;能够快速随机访问;但对中间元素插入或删除时,性能较差(需要移动大量元素);
ArrayList只支持动态扩容,不支持缩容? 允许元素为null;
LinkedList使用双链表实现,实现了内部类Node节点(包括item、next、prev字段),并维护一个first、last节点的指针;
适合随机插入、删除,随机访问比较慢;也是非线程安全;可以被当作堆栈、队列或双端队列使用;允许元素为null;
CopyOnWriteArrayList是ArrayList的线程安全版本;在set、add、remove、removeRange、clear等方法中,使用ReentrantLock控制并发访问(即lock、unlock);
‘写时复制’,读写分离,即写操作的同时,不会影响读操作;(注意Vector的读操作都不能并发执行!)写操作代价很大,故适用于遍历操作远多于写操作的场景;
通过快照来保证读操作不用加锁;注意:Object[] array数组的volatile可以让修改对所有线程立即可见,但仍有延迟,所以说只保证最终一致性;
(问题来了,当写操作很多的时候,CopyOnWriteArrayList和原始的Vector,以及synchronized+ArrayList,哪个性能更高?)
http://ifeve.com/java-copy-on-write/
https://yq.aliyun.com/articles/594457

Vector jdk1.0
ArrayList+Collections.synchronizedList JDK1.2
LinkedList+Collections.synchronizedList JDK1.2
CopyOnWriteArrayList JDK1.5

jdk为啥没有提供CopyOnWriteMap之类的?(并不是因为有了ConcurrentHashMap)
可以自己简单实现,参考http://www.cnblogs.com/dolphin0520/p/3938914.html

PriorityQueue、PriorityBlockingQueue:
PriorityQueue是无界优先级队列,实现Queue接口,元素不能为null,且必须可以比较;非线程安全;迭代器也会抛ConcurrentModificationException;当队列为空,取元素会阻塞;插入永远不会阻塞;
利用二叉堆实现(balanced binary heap),以Object[] queue数组存放元素,默认初始容量为11;默认小顶堆(即最小优先级队列)
PriorityBlockingQueue是PriorityQueue的线程安全版本,实现BlockingQueue接口;(为啥叫BlockingQueue,不叫ConcurrentQueue,因为是阻塞队列;jdk也实现了非阻塞的队列ConcurrentLinkedQueue等;)
利用UNSAFE的CAS、Condition和ReentrantLock实现同步及线程安全;不会抛ConcurrentModificationException;
(前提知识:堆数据结构除了堆排序,还有优先级队列;堆排序有大顶堆和小顶堆,优先级队列也有最大优先级队列和最小优先级队列;《算法导论》)
(最大优先级队列的一个经典应用是,作业调度如yarn;最小优先级队列的一个经典应用是Prim算法和Dijkstra算法;)
(优先级队列一定要用堆实现吗(包括二叉堆、斐波那契堆、二项堆)?优先级队列把队列看成集合;)

ArrayBlockingQueue和LinkedBlockingQueue:
ArrayBlockingQueue是有界普通队列(FIFO),一旦初始化,容量无法改变;当队列为空,取元素会阻塞;当队列为满,插入元素也会阻塞;
以Object[]items数组存放元素;利用Condition和ReentrantLock实现同步及线程安全;(notEmpty和notFull两个Condition)不会抛ConcurrentModificationException;
LinkedBlockingQueue是基于链表的有界普通队列(FIFO),内部类Node有item和next字段;不会抛ConcurrentModificationException;
也是利用Condition和ReentrantLock实现同步及线程安全;(notEmpty和notFull两个Condition;takeLock和putLock两把锁;)
LinkedBlockingQueue的吞吐量要高于ArrayBlockingQueue?(因为锁的分离,插入和删除可以同时进行;)
https://blog.youkuaiyun.com/javazejian/article/details/77410889?locationNum=1&fps=1 !!!

LinkedBlockingQueue和LinkedBlockingDeque:
LinkedBlockingDeque是基于链表的有界普通双端队列(同时支持FIFO和FILO),内部类Node有item、prev和next字段;不会抛ConcurrentModificationException;
也是利用Condition和ReentrantLock实现同步及线程安全;(notEmpty和notFull两个Condition;但只有一把锁;)

http://ifeve.com/java-blocking-queue/ !!!

SynchronousQueue和LinkedTransferQueue:
SynchronousQueue实现BlockingQueue接口,容量只有1(或者1都算不上),插入操作必须等删除操作先执行;不能用peek来窥探,要么直接remove;
不能iterate因为没元素;size返回永远是0;isEmpty返回永远是true;一切插入删除都用transfer方法;
内部类TransferStack是Dual Stack;而TransferStack的内部类SNode代表一个stack节点;
内部类TransferQueue是Dual Queue;而TransferQueue的内部类QNode代表一个queue节点;
通过在构造函数指定fair,来选择使用TransferStack还是TransferQueue;(其中Queue对应fair,Stack对应nonfair)
利用LockSupport和UNSAFE的CAS实现同步及线程安全;一个重要的应用是线程池;
https://www.jianshu.com/p/c4855acb57ec !!!
LinkedTransferQueue实现TransferQueue接口,而后者继承BlockingQueue接口;可以看成是LinkedBolckingQueue和SynchronousQueue的合体;(只有Dual队列,没有Dual栈的功能)
内部类Node是队列节点;所有队列操作都用xfer方法实现;采用了预占模式和松弛技术(slack threshold为2);
通过直接传递减少阻塞,不是完全不阻塞!(不过消息队列的意义,不是解耦吗,这样消费者和生产者耦合了。。)
https://www.jianshu.com/p/42ceaed2afe6 !!!
https://blog.youkuaiyun.com/qq_38293564/article/details/80593821
(前置知识:双重队列Dual Queue是指,它的节点可以代表一个数据或一个请求,用isData表示;)

ConcurrentLinkedQueue和ConcurrentLinkedDeque:
ConcurrentLinkedQueue是基于链表的无界普通队列(FIFO),与LinkedBlockingQueue区别是,它是无锁、非阻塞的;
内部类Node有item和next字段;纯利用UNSAFE的CAS实现同步及线程安全;不会抛ConcurrentModificationException;
ConcurrentLinkedDeque是基于链表的无界普通双端队列(同时支持FIFO和FILO),也是无锁、非阻塞的;
内部类Node有item、prev和next字段;纯利用UNSAFE的CAS实现同步及线程安全;不会抛ConcurrentModificationException;
https://www.imooc.com/article/details/id/26439 !!!
http://ifeve.com/concurrentlinkedqueue/ !!!
两者都借鉴了LinkedTransferQueue的思想!!!
总结:并发量特别高的时候,适合无锁实现!

DelayQueue:
DelayQueue是利用PriorityQueue实现的无界延迟队列(将PriorityQueue作为成员变量,也实现BlockingQueue接口);
数据过期expired才能移出队列,即getDelay获取的时间小于0;
也是利用Condition和ReentrantLock实现同步及线程安全;常见的应用是缓存系统;
https://www.jianshu.com/p/15f777b72716

Vector、Stack和ArrayDeque(Deque接口):
Stack是Vector的子类,提供了push、pop、peek等栈操作;也是利用synchronized实现线程安全;
ArrayDeque是双向循环队列,是非线程安全的,当做栈使用时,比Stack快;当做队列使用时,比LinkedList快;
ArrayDeque也是基于数组实现,Object[] elements,长度为2的幂方;
当数组满(即head and tail相等)时,会进行双倍扩容(doubleCapacity),也是通过System.arraycopy;
其中offerLast和addLast等价,offerFirst和addFirst等价,removeFirst和pollFirst等价,removeLast和pollLast等价,
getFirst和peekFirst等价,getLast和peekLast等价;add和addLast等价;offer和offerLast等价;
remove和removeFirst等价;poll和pollFirst等价;element和getFirst等价;peek和peekFirst等价;(栈操作)
push和addFirst等价(栈操作);pop和removeFirst等价;(栈操作)

Collections类的synchronizedCollection、synchronizedSet、synchronizeMap方法等:
Collections类通过分别构造SynchronizedCollection、SynchronizedSet、SynchronizedMap、SynchronizedList内部类,本质上通过synchronized (mutex) 实现同步;

WeakReference、PhantomReference、SoftReference、FinalReference、ReferenceQueue、Finalizer和Reference:
http://www.cnblogs.com/skywang12345/p/3154474.html
http://developer.51cto.com/art/200906/128189.htm
http://www.cnblogs.com/xdouby/p/6701941.html
https://www.jianshu.com/p/e66930caca9c
http://lovestblog.cn/blog/2015/05/12/direct-buffer/
https://www.infoq.cn/article/jvm-source-code-analysis-finalreference
http://blog.ragozin.info/2016/03/finalizers-and-references-in-java.html
Reference是一个抽象类,代表一个引用对象,主要和gc有关(是为了更好的垃圾回收);
Reference有四种状态,Active、Pending、Enqueued、Inactive;
Reference主要方法有get、clear、enqueue、isEnqueued,并维护一个ReferenceQueue字段;
ReferenceQueue是一个引用队列,主要方法有enqueue、remove、poll;
WeakReference、PhantomReference、SoftReference、FinalReference都继承Reference;
(StrongRerence这个类并不存在,而是在JVM底层实现;默认的对象都是强引用类型;宁愿抛出OutOfMemory的错误,也不会回收被强引用所引用的对象;)
(SoftReference只有在JVM内存不足的情况下,才会被垃圾回收器回收;通常用于实现内存敏感的缓存;)
(注意:当一个SoftReference是strongly reachable时,或者说当前正在使用,是不会被清除的,因此可以打造成熟的缓存系统;)
(WeakReference当对象只剩下一个weak引用,gc的时候就会回收;)
(WeakReference生命周期只能存活到下次GC前?)
(PhantomReference的get方法总是返回null,因此无法访问对应的引用对象;PhantomReference的应用并不多,其中一个应用是sun.misc.Cleaner类;)
(PhantomReference必须和引用队列联合使用,进入队列后jvm不会自动回收,需要人为调用clear方法后才最终释放,这是使用PhantomReference的关键;)
(PhantomReference随时会被回收, 创建了可能很快就会被回收?)
(FinalReference由jvm自己使用,外部无法调用;Finalizer继承FinalReference;)
(jvm将实现了Object.finalize方法的实例标识为finalizer类型,注册为一个Finalizer对象,并加到到对象链中,
有一个FinalizerThread线程负责从对象链获取Finalizer对象,执行runFinalizer函数,最终调用Object.finalize

;)

ReentrantLock和Synchronized:
ReentrantLock实现Lock和Serializable接口;其中Lock接口有lock、lockInterruptibly、tryLock、unlock、newCondition方法;
(注意:Lock接口就提供了Condition newCondition();)
(Condition接口有await、awaitUninterruptibly、awaitNanos、awaitUntil、signal、signalAll方法;)
(Condition和Object的notify、notifyAll、wait非常相似;区别是每个对象可以有多个等候集;)
(Condition必须和Lock一起使用吗?Condition可以和Synchronized搭配使用吗?)
(Lock可以用notify、notifyAll、wait,而不用Condition吗?)
(Condition实例也是普通的Object,因此也有notify、notifyAll、wait方法;为了避免混淆,不建议把它当做普通Object使用;)
ReentrantLock被最后一个加锁,但没有解锁的线程占有;
(是否需要按照FILO的方式释放?即后锁住的先释放?还是任意顺序释放即可?因为只能被同一个线程重入,所以不存在这个问题)
公平锁效率更低,但更稳定,不容易导致饥饿;
锁的公平不能保证线程的调度也是公平的;(可能每次都是被同一个线程占有;)
tryLock、lockInterruptibly可以避免死锁?(可中断、可定时和可轮询的锁获取模式)
(注意,虽然lockInterruptibly可以中断方式获取锁,但必须在外面调用Thread.interrupt触发中断;)
内部抽象类Sync继承AbstractQueuedSynchronizer抽象类(AQS),而后者继承AbstractOwnableSynchronizer抽象类;
内部类NonfairSync和FairSync继承Sync,即非公平锁和公平锁;
ReentrantLock同时将Sync作为成员变量,因此可直接用NonfairSync或FairSync初始化Sync;(默认非公平锁,即允许线程插队)
(事实上Sync默认是非公平锁,见nonfairTryAcquire方法;)
(公平锁唯一的区别是,判断时加了hasQueuedPredecessors,即确保没有等待了更久的线程;通过对线程Thread节点链表即CLH队列的查找;)
(原生的CLH队列是用于自旋锁,但Doug Lea把其改造为阻塞锁;)
(c==0说明没有线程正在竞争该锁,c!=0说明有线程正拥有该锁;)
(每次线程重入该锁都会+1,unlock都会-1,为0代表释放锁;)
https://www.jianshu.com/p/279baac48960 !!!
重入锁意思是可通过acquires的setState重新设置状态;(注意setState不需要CAS同步,因为此时已经获取锁;)
https://www.jianshu.com/p/f7d05d06ef54
https://www.cnblogs.com/xrq730/p/4979021.html
https://www.jianshu.com/p/e4301229f59e

ReentrantLock比Synchronized更加危险,因为容易忘记在finally中释放锁;(虽然findbugs有检查未释放锁的功能)
有些场景只能使用内置锁(比如对方法加锁),有些场景只能使用Lock(比如需要防止死锁、或者实现公平锁)
ReentrantLock最多重入Integer.MAX_VALUE次;
synchronized也可以重入;
synchronized static方法锁住的是类!!!
synchronized(Test.class)锁住的也是类!!!
https://www.jianshu.com/p/96c89e6e7e90

Synchronized原理:
利用javap -c 类名反编译可以看到Synchronized块对应的字节码monitorenter和monitorexit;
(同步方法则对应于ACC_SYNCHRONIZED;)
https://www.jianshu.com/p/5c4f441bf142
http://www.cnblogs.com/mingyao123/p/7424911.html
https://baijiahao.baidu.com/s?id=1580364922566928882&wfr=spider&for=pc
https://www.cnblogs.com/paddix/p/5367116.html
https://blog.youkuaiyun.com/javazejian/article/details/72828483 !!!
http://cmsblogs.com/?p=2071

AQS通过CAS无锁操作来维护CLH队列;
synchronized的底层也是一个基于CAS操作的等待队列,但JVM实现的更精细;

Condition:
注意,Condition.signal前必须确保已拥有该锁(即已先执行了ReentrantLock.lock)
Condition.await会自动释放锁!!!它从同步队列队首移除,然后加入等待队列队尾;
await状态的线程被signal唤醒后会重新获取锁;(是隐式的、自动的);
https://www.cnblogs.com/sheeva/p/6484224.html !!!
https://www.cnblogs.com/dolphin0520/p/3920385.html
https://blog.youkuaiyun.com/javazejian/article/details/75043422 !!!
以生产者消费者为例,使用Condition最大好处是一个锁可以构造多个条件队列(生产者消费者各一个队列),让生产者退出前唤醒消费者,消费者退出前唤醒生产者,
如果用传统Synchronized+Object的notify、notifyAll、wait,因为只有一个队列,生产者唤醒的可能还是生产者,反之亦然;当然Lock和传统方法都可以使用多个锁,
但那样效率有时候不高;但有的时候确实需要多个锁,比如LinkedBlockingQueue,但那是为了生产者消费者同时进行;不管怎样,Lock+Condition提供了更高的灵活性;

AbstractQueuedSynchronizer:
内部类Node是线程节点,即一个节点代表一个线程(封装了Thread thread),有prev、next字段,是双向链表;
(Node的SHARED代表线程处于共享模式、EXCLUSIVE代表处于互斥模式、CONDITION代表处于等待某个条件、CANCELLED代表已经取消;)
state记录同步状态;(状态的设置是CAS原子的;)
AQS依靠系统阻塞来挂起线程;(即LockSupport的park、unpark)
AQS的内部类ConditionObject实现Condition接口;(ConditionObject是ReentrantLock#newCondition的背后实现;)
ReentrantLock/Semaphore/CountDownLatch/FutureTask都依赖AQS;
(Semaphore和CountDownLatch都是共享锁,ReentrantLock是排它锁;)
AQS包括同步队列(sync queue)和等待队列(condition queue);(前者是一般的队列,且是双向链表;后者专指Condition条件队列,是单向链表;)
(都使用相同的Node结构;等待队列结点状态只有两种即CANCELLED和CONDITION;一个用nextWaiter,一个用next字段;)
(AQS中只能存在一个同步队列,但可拥有多个等待队列;每个Codition对应一个等待队列;)
(同步队列可以是公平或非公平的;等待队列是公平的,即FIFO;)
https://www.jianshu.com/p/be2dc7c878dc !!!
https://www.cnblogs.com/waterystone/p/4920797.html

ReentrantReadWriteLock和StampedLock:
ReentrantReadWriteLock实现ReadWriteLock接口,而后者并没有继承Lock接口,后者定义了readLock方法和writeLock方法;
内部类ReadLock和WriteLock才实现了Lock接口,内部类Sync继承AQS抽象类,内部类NonfairSync和FairSync又继承Sync(默认非公平);
ReentrantReadWriteLock将ReadLock、WriteLock、Sync作为成员变量;
(而ReadLock和WriteLock都依赖Sync,将它作为成员变量;)
(写锁可以降级为读锁,但反过来不行;)
(锁降级的方式:先获取写锁,再获取读锁,最后释放写锁;)
(读锁是共享锁,写锁是排它锁;)
(写锁支持Condition,而读锁不支持会抛UnsupportedOperationException;)
(Sync的readHolds字段是ThreadLocal,即线程私有的;)
(读锁和写锁在一个int中,也就是32位,其中高16位代表读锁,低16位代表写锁的获取次数)
(最多分别支持65535个递归读锁和写锁;)
(读锁可以被多个线程重入,而写锁只能被一个线程重入;)
(读锁在获取时,如果写锁已经被获取并且该线程不是当前线程的话,则获取读锁失败;见tryAcquireShared方法)
(读锁释放时,将同步状态减去读状态即可,见tryReleaseShared方法)
ReentrantReadWriteLock的优点是,当读远多于写的时候可以提高程序的并发量和吞吐量;
ReentrantReadWriteLock的缺点是,当读并发很高时读操作长时间占有锁,导致写锁长时间无法获取而导致线程饥饿;

StampedLock即读写并发锁,是读写锁的一个改进版本;
StampedLock的写锁writeLock是独占锁,且是不可重入的;
StampedLock的读锁readLock是非独占锁、悲观锁,也是不可重入的;
StampedLock还有一个乐观读锁tryOptimisticRead,因为没有阻塞,不存在重入问题;
(判断标记位是否有被修改,如果有修改就再读一次;)
(以上三种都不支持Condition;)
StampedLock没有实现Lock或ReadWriteLock接口;
内部类WNode是等待节点,封装了thread,且mode为读或写,有prev和next是双链表;
利用whead、wtail指向CLH队列的头尾;
内部类ReadLockView、WriteLockView实现Lock接口,ReadWriteLockView实现ReadWriteLock接口;
tryConvertToWriteLock可以将读锁晋升为写锁(当前已持有写锁则返回、处于读模式但没有更多读取者、处于乐观读锁模式且写锁可用);
tryConvertToOptimisticRead可以转化为乐观读锁;
https://segmentfault.com/a/1190000015808032?utm_source=tag-newest
https://www.cnblogs.com/huangjuncong/p/9191760.html

UNSAFE、LockSupport、CAS:
https://www.cnblogs.com/thomas12112406/p/6510787.html
https://www.cnblogs.com/throwable/p/9139947.html
http://www.cnblogs.com/xrq730/p/4976007.html
sun.misc.Unsafe包不能直接使用,通过反射才能使用?
Unsafe类使用了单例模式,需要通过一个静态方法getUnsafe()来获取;
LockSupport直接操作Thread(不需要依赖监视器,与wait/notify没有交集),而Object的wait/notify是被动的方法;
LockSupport的park也可以响应Thread的interrupt中断?
unpark函数可以先于park调用!!!不用担心时序问题(而wait/notify无法做到这点)

Semaphore即信号量:
Semaphore与锁不同的是,它能限制线程的数量,或最大并发数;(如同停车场系统,Semaphore相当于看守人)
Semaphore利用Sync(将它作为成员变量),其中Sync是AQS的子类,Sync也分为NonfairSync和FairSync;(默认非公平)
(注意:Semaphore的permits就是AQS的state;)
(可以在初始化时指定permits个数;)
(acquire从信号量获取许可,可以一次获取多个;)
(release给信号量释放许可,可以一次释放多个;)
(tryAcquire和Lock的tryLock类似;)
(Semaphore使用的是AQS的共享模式;)
http://ifeve.com/concurrency-semaphore/#more-14753

CountDownLatch即闭锁:
CountDownLatch能够使一个或多个线程等待其他线程完成各自的工作后再执行;
(场景一:开启多个线程分块下载大文件,各线程只下载固定一截,最后由另外一个线程来拼接所有的分段;)
(场景二:对多个线程计时,主线程再打印;)
CountDownLatch没有实现或继承任何抽象类或接口;
CountDownLatch利用Sync(将它作为成员变量),其中Sync是AQS的子类;(没有公平非公平问题)
和CyclicBarrier的区别是,它是单向的,即count不能重新设置;
(注意:CountDownLatch的count就是AQS的state;)
(可以在初始化时指定count;)
(await方法用于阻塞当前线程,直到count变为0;与Condition的await方法同名且有点类似,如都可以被中断;)
(CountDownLatch使用的是AQS的共享模式;)
(countDown建议放在finally里执行?)
https://www.iteye.com/topic/1002652
http://www.importnew.com/21889.html
https://blog.youkuaiyun.com/wtopps/article/details/84952842

CyclicBarrier即栅栏:
CyclicBarrier是线程互相等待对方到某个状态(或公共屏障点);
(场景一:赛马程序,即所有赛马到达栅栏前,再开始跑;)
CyclicBarrier没有实现或继承任何抽象类或接口;
(因为可以被重用(reset方法),所以叫Cyclic(周期的、循环的);)
(await方法(调用dowait)用于阻塞当前线程,直到parties个线程到达barrier,或者发生中断、超时;)
CyclicBarrier利用ReentrantLock和Condition实现同步;(间接依赖AQS!)
在CyclicBarrier中,同一批线程属于同一代,即同一个Generation;
(当有parties个线程到达barrier,generation就会被更新换代;也就是count从parties变为0;)
https://www.cnblogs.com/skywang12345/p/3533995.html
https://blog.youkuaiyun.com/wtopps/article/details/84436498

FutureTask:
FutureTask用于一个线程获取另一个线程的执行结果?
(FutureTask+ExecutorService完全可以用Callable+ExecutorService+Future实现;)
(FutureTask只是对Callable多了一层封装,同时又有Future的特性;或者说,FutureTask是Future接口的具体实现类;)
(FutureTask还可以直接构造Thread执行,而不用ExecutorService;因为它也有Runnable接口特性;FutureTask是Runnable和Callable的结合)
FutureTask实现RunnableFuture接口;而后者继承Runnable和Future接口;(接口多继承)
(Future接口有get、cancel、isDone、isCancelled方法;)
(也就是说Future提供了三种功能:判断任务是否完成、取消任务、获取任务执行结果;)
jdk1.8中,FutureTask不再使用AQS而是直接用CAS维护state变量;
(任务state可以是NEW、COMPLETING、NORMAL、CANCELLED、EXCEPTIONAL、INTERRUPTING、INTERRUPTED;)
FutureTask封装了Thread、Callable、WaitNode;
(其中WaitNode内部类也封装了Thread、以及next字段;代表等待的线程;多个WaitNode构成阻塞队列;)
https://www.cnblogs.com/dolphin0520/p/3949310.html
https://www.jianshu.com/p/55221d045f39

Exchanger:
Exchanger用于线程间交换数据,使用exchange方法,第一个执行exchange时会等待第二个也执行exchange;
(在遗传算法和交互管道流设计中使用比较多;一般在两个线程之间交换,在多线程下,互相交换数据的两个线程是不确定的)
Exchanger采用无锁算法,完全利用Unsafe的CAS实现;
内部类Node封装了Thread和要交换的数据;为了线程安全,Node使用ThreadLocal封装为Participant类;
Exchanger有单槽位和多槽位之分,单槽在同一时刻只能两个线程交换数据,多槽是多个线程同时进行两个的数据交换,彼此不受影响;
(若竞争小,会采用单槽位进行交换数据;竞争比较激烈,会转到多槽位的交换,可以提高吞吐量)
(slotExchange是单槽位交换,arenaExchange是多槽位交换;其中多槽位利用Node数组arena实现;)
https://blog.youkuaiyun.com/u014634338/article/details/78385521

Phaser:
Phaser是阶段器,用来控制多个线程分阶段共同完成任务;(支持任务在多个点都进行同步)
Phaser和CyclicBarrier类似,也可以重用,但更灵活;
(如果使用CountDownLatch,必须创建多个CountDownLatch对象,每一阶段都需要一个CountDownLatch对象)
内部类QNode实现ForkJoinPool的ManagedBlocker接口;同时封装了Thread、Phaser和next等;用于构造等待节点和等待队列;
使用synchronized和Unsafe的CAS实现线程安全;
https://blog.youkuaiyun.com/u010739551/article/details/51083004

Runnable和Callable:
Runnable无法直接返回结果,要获取子线程的执行结果,需要用Handler将结果返回到调用线程;
Callable可以直接返回子线程执行结果;

ForkJoinTask、ForkJoinPool、ForkJoinWorkerThread:
ForkJoinTask也实现了Future接口;(FutureTask是间接实现)
ForkJoinTask有两个子类,RecursiveAction和RecursiveTask;(都是抽象类)
(RecursiveTask可以计算递归类型,如Fibonacci,返回结果)
(RecursiveAction的区别是,不返回结果,如原地排序)
ForkJoinTask可以直接执行compute方法,也可以提交给ForkJoinPool执行;(forkJoinPool.submit(task)或invoke)
(不管哪种,主要逻辑都在compute方法实现;主要是拆分任务,和调用fork和join方法)
(fork主要将task存入当前线程的workQueue工作队列;注意,当前线程必须是ForkJoinWorkerThread类型;)
(ForkJoinWorkerThread只是封装了ForkJoinPool的WorkQueue类型;)
(WorkQueue类中又有ForkJoinWorkerThread字段;)
(join主要是阻塞当前线程并等待获取结果;)
ForkJoinTask同时使用了Unsafe的CAS、Object的wait/notifyAll、synchronized、ReentrantLock实现;

ForkJoinWorkerThread是Thread的子类;
ForkJoinWorkerThread执行ForkJoinTask,被ForkJoinPool管理,每个线程对应一个双端队列WorkQueue;
内部类InnocuousForkJoinWorkerThread是ForkJoinWorkerThread的子类,封装了ThreadGroup;
ForkJoinWorkerThread大量使用Unsafe的CAS;

ThreadPoolExecutor、ScheduledThreadPoolExecutor、ForkJoinPool、Executors:(jdk1.5之前没有线程池?)
(注意:ExecutorService是接口,它继承Executor接口;)
ThreadPoolExecutor也是继承AbstractExecutorService抽象类;(这三种线程池的共同点)
利用BlockingQueue workQueue存放等待执行的任务,转交给工作线程;
(可以用ArrayBlockingQueue或LinkedBlockingQueue初始化;)
利用HashSet workers维护工作线程;
内部类Worker继承AQS,并实现Runnable,代表一个工作线程;
corePoolSize用于设置线程池大小(允许同时运行的最大线程数);
(线程池大小需考虑CPU数量、内存大小、任务是计算密集型还是IO密集型等因素)
拒绝策略有AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy;
线程池的关闭:shutdown不会立即终止,shutdownNow立即终止(并尝试打断正在执行的任务);
使用ReentrantLock和Condition控制访问;

http://www.cnblogs.com/dolphin0520/p/3932921.html
http://www.cnblogs.com/aspirant/p/6920418.html

ScheduledThreadPoolExecutor是ThreadPoolExecutor的子类;(同时实现ScheduledExecutorService接口,而后者继承ExecutorService接口)
(即newScheduledThreadPool的具体实现;)

ForkJoinPool继承AbstractExecutorService抽象类,而后者实现ExecutorService接口;
ForkJoinPool将一个大任务拆分成多个小任务;
(fork负责将小任务分发给其他线程同时处理;join负责将多个线程处理结果进行汇总;分而治之、工作窃取)
(为了减少窃取线程和被窃取线程的竞争,通常使用双端队列;被窃取线程永远从头部拿任务,窃取线程永远从尾部拿任务;)
(push/pop只能被队列的所有者线程调用,而poll可以被其他线程调用;)
ForkJoinPool能够使用少数线程完成很多具有父子关系的任务,如使用4个线程完成200万个任务,而ThreadPoolExecutor是不可能完成的;
(ForkJoin类似于单机版的MapReduce;)
内部类DefaultForkJoinWorkerThreadFactory是构造ForkJoinWorkerThread的静态工厂类;
ForkJoinPool大量使用Unsafe的CAS;

https://blog.youkuaiyun.com/Holmofy/article/details/82714665 !!!
https://www.cnblogs.com/lixuwu/p/7979480.html
http://ifeve.com/java-fork-join-framework/#more-35602
https://www.cnblogs.com/senlinyang/p/7885964.html !!!

Executors提供static方法来构造线程池,该线程池可以是ThreadPoolExecutor、ScheduledThreadPoolExecutor、ForkJoinPool、ThreadFactory;
(还可以是对(Scheduled)ThreadPoolExecutor的封装,如FinalizableDelegatedExecutorService、DelegatedScheduledExecutorService等;)
(其中ThreadFactory具体有DefaultThreadFactory、PrivilegedThreadFactory等;)

Executors提供了5种线程池:
newCachedThreadPool,即可缓存的线程池,如果线程池大于所需,可以回收,如果不够,可以扩大,很智能;
newFixedThreadPool,即固定大小的线程池,每提交任务就创建线程,直到达到线程池的最大值;
newScheduledThreadPool,是一个大小无限的线程池,支持定时及周期性任务执行;(即ScheduledThreadPoolExecutor)
newSingleThreadExecutor,即只有一个线程的线程池,单线程串行执行所有任务,保证任务按提交顺序执行;
newWorkStealingPool:即work-stealing线程池;(jdk1.7引入)
newSingleThreadScheduledExecutor?也是对应ScheduledThreadPoolExecutor

AtomicInteger、AtomicLong、AtomicBoolean、AtomicReference、AtomicStampedReference、AtomicMarkableReference:
https://blog.youkuaiyun.com/javazejian/article/details/72772470 !!!
AtomicInteger也是Number的子类;
AtomicInteger是对volatile int value的封装,不是final的,所以值可以改变;
AtomicInteger利用unsafe实现原子操作;

AtomicLong也是Number的子类;
AtomicLong是对volatile long value的封装,不是final的,所以值可以改变;
AtomicLong利用unsafe实现原子操作;

AtomicBoolean没有父类;
AtomicBoolean是对volatile int value的封装,不是final的,所以值可以改变;
AtomicBoolean利用unsafe实现原子操作;

AtomicReference没有父类,但提供了泛型AtomicReference ;
AtomicReference是对volatile V value的封装,不是final的,所以值可以改变;
AtomicReference利用unsafe实现原子操作;
(AtomicReference是对”对象”进行原子操作;可以是任意对象!!!)
https://segmentfault.com/a/1190000015831791?utm_source=tag-newest !!!

AtomicStampedReference没有父类,但提供了泛型AtomicStampedReference ;
AtomicStampedReference利用静态内部类Pair维护T reference和int stamp的组合;
AtomicStampedReference是对volatile Pair pair的封装,不是final的,所以值可以改变;
(注意Pair中的reference和stamp不可变,需要重新创建Pair对象;见casPair方法;)
AtomicStampedReference利用unsafe实现原子操作;
AtomicStampedReference是加了版本号的AtomicReference,可以解决CAS中的ABA问题;
(AtomicStampedReference如何保证每次修改对象引用,stamp也会被修改?stamp自身不会出现ABA吗?通过stamp只增不减来保证?让用户自己控制?)

AtomicMarkableReference和AtomicStampedReference区别是,Pair中维护的是boolean mark,而不是int stamp;
AtomicMarkableReference也可以解决CAS中的ABA问题;
(AtomicStampedReference关心的是动过几次,AtomicMarkableReference关心的是有没有动过;)

AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray:
AtomicIntegerArray是对final int[] array的封装;
AtomicIntegerArray利用unsafe实现原子操作;
AtomicIntegerArray会将当前数组复制一份,不会影响到传入的数组(利用array.clone());

AtomicLongArray是对final long[] array的封装;
AtomicLongArray利用unsafe实现原子操作;
AtomicLongArray会将当前数组复制一份,不会影响到传入的数组(利用array.clone());

AtomicReferenceArray是对final Object[] array的封装;
AtomicReferenceArray利用unsafe实现原子操作;
AtomicReferenceArray会将当前数组复制一份,不会影响到传入的数组(利用Arrays.copyOf);

AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater:
AtomicIntegerFieldUpdater利用反射,对volatile int类型提供原子更新;
AtomicIntegerFieldUpdater是一个抽象类,具体实现是内部类AtomicIntegerFieldUpdaterImpl;

AtomicLongFieldUpdater利用反射,对volatile long类型提供原子更新;
AtomicLongFieldUpdater是一个抽象类,具体实现是内部类CASUpdater、LockedUpdater;

AtomicReferenceFieldUpdater利用反射,对volatile引用类型提供原子更新;
AtomicReferenceFieldUpdater是一个抽象类,具体实现是内部类AtomicReferenceFieldUpdaterImpl;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值