# JAVA与ABA问题

* This is a modification of the Michael & Scott algorithm,* adapted for a garbage-collected environment, with support for* interior node deletion (to support remove(Object)).  For* explanation, read the paper.** Note that like most non-blocking algorithms in this package,* this implementation relies on the fact that in garbage* collected systems, there is no possibility of ABA problems due* to recycled nodes, so there is no need to use "counted* pointers" or related techniques seen in versions used in* non-GC'ed settings.

2. 说这个类的实现依赖于“在GC系统中，there is no possibility of ABA problems due to recycled nodes"。问题在于，什么叫”recycled nodes”？

1. 我们在CAS中比较对节点的引用 & 我们复用节点。假如queue初始的状态是A -> E。在变化后的状态是A -> X -> E。那么我们在CAS中比较对A的引用时，就无法看出状态的变化。“复用”，就是像这个例子一样，把同一个节点再次加个队列。
2. 我们在CAS中比较对节点的引用 & 某个new出来的节点A2的地址恰好和A1的地址相同。

GC环境和无GC的环境(如C++)的不同在于第二种情况。即，在JAVA中第，第二种情况是不可能发生的。原因在于，在我们用CAS比较A1和A2这两个引用时，暗含着的事实是——这两个引用存在，所以它们所引用的对象都是GC root可达的。那么在A1引用的对象还未被GC时，一个新new的对象是不可能和A1的对象有相同的地址的。所以A1 != A2。

A common case of the ABA problem is encountered when implementing a lock-free data structure. If an item is removed from the list, deleted, and then a new item is allocated and added to the list, it is common for the allocated object to be at the same location as the deleted object due to optimization. A pointer to the new item is thus sometimes equal to a pointer to the old item which is an ABA problem.

    public boolean offer(E e) {
checkNotNull(e);
final Node<E> newNode = new Node<E>(e);

for (Node<E> t = tail, p = t;;) {
Node<E> q = p.next;
if (q == null) {
// p is last node
if (p.casNext(null, newNode)) {
// Successful CAS is the linearization point
// for e to become an element of this queue,
// and for newNode to become "live".
if (p != t) // hop two nodes at a time
casTail(t, newNode);  // Failure is OK.
return true;
}
}
else if (p == q)
// We have fallen off list.  If tail is unchanged, it
// will also be off-list, in which case we need to