Looked at the online about the chain list of non-lock operation, writing is not clear, so that their own part of the main use of concurrent and the contract of the CAS operation.
1. End of List insertion
The node to be inserted is: cur
Tail Node: pred
Basic Insertion Method:
do{
pred = Find_tail (); Re-find tail node
}(! pred.next.compareAndSet (NULL, cur)) Pred.next is null, then it points to cur, not a new node is inserted
This insertion method is not tagged, and it is possible to remove this method if the list is not involved.
However, if there is a delete operation, the pred node may be deleted, so we need to add a tag bit to determine if the pred is deleted (False is not deleted)
do{
pred = Find_tail ();
}(! pred.next.compareAndSet (NULL, cur, false, false)); Check whether Pred.next is marked false and marked false
Because we insert is the CAS operation for Pred.next, so although to determine whether the pred is deleted, we can only see its next field of the tag , so when the deletion and here to match the next bit to true to make this addition unsuccessful
Note that the next position here is not the next node, is pred itself, because only from pred to see if it is deleted, so the data structure of the node does not contain flag, the next field of the node contains flag, This structure is specific reference atomicmarkablereference
If it is not possible to determine if pred is false first, all operations must be done in CAs, because the moment of judgment is ok but not the time to execute the CAS.
(TIP: Because it's the end of the queue, the next field is null, but it still contains the tag bits, each new node-tail is added with Node.next = new atomicmarkablereference<node> (null,false))
2. Linked list Delete node
The node to be deleted is: cur
bo=
SUCC = Cur.next; Re-find Next node
if (Cur.next = = true) break; Thread has deleted its logic
pred = pred (cur); Find Pred node
Flag1 = Cur.next.compareAndSet (SUCC, SUCC, False, true); The first CAs resets cur.next to true to prevent adding and repeating deletions
if (! Flag1) continue;
Flag2 = Pred.next.compareAndSet (cur, succ, false, false); The second CAs points pred.next to succ and resets the SUCC to False
if (! Flag2) continue;
} (0);
Here two CAS operations, the first set-up, that is, the so-called Tombstone , and the addition of the node to echo, after the mark is over, after the second CAs execution, the addition to this node is unsuccessful
This CAS failure indicates that there are additional threads to delete operations or CAS before there are add operations to Cur's next (succ change), which returns to try again
The second time the original point to cur pred.next point to succ, physical deletion , where SUCC has not changed, because the first CAS success after the next set of other threads can neither add nor delete
But pred can be deleted, pred is removed and causes Pred.next to set, this time CAs fails.
Here the second CAS operation may also have the same code elsewhere, if this thread is blocked after the first CAs call, allowing other threads to see this tag and help with node deletion and clearing, which is the core idea of the wait free design
3. List A node insert
The principle of implementation is the same, not much to repeat, must pay attention to and delete the judgment process is to ensure self-consistent.
Lock-free operation of linked list (JAVA)