ABA is a well-known problem at CAS based lock-free data structure. C++ supports std::atomic for abitrary data type but it isn’t sometimes lock free. You can check it with below.
1 |
|
Result will be looks like.
1 |
|
In fact, CAS-possible data size is limited to the HW support. However, most of HW supports only memory size CAS operation. If it is 32-bit computing unit, it usually supports 32-bit CAS. If it is 64-bit computing unit, it usually supports 64-bit CAS. Therefore, most of CAS based data structures use a pointer to work. Below lock-free queue uses this.
1 |
|
However, it has a problem(You can try this in own). Since it checks only the pointer to decide whether it changed or not, it can’t know when it just reuses the same address. Therefore, above scenario will be a problem.
Let’s assume there are one CAS-based lock-free queue $Q$ and two threads $T_1, T_2$. $Q$ has $A$ and $B$ at the initial state. Now $T_1$ access $Q$, it caches $A$ as a top of stack and $B$ as a next element of the top. However $T_1$ fall a sleep right after. Now $T_2$ access $Q$, it pops $A$ and $B$. After that $T_2$ reuses $A$’s address and push it to the $Q$. Now $T_1$ wakes up, $T_1$’s CAS will be success because it checks only top of the stack. Therefore, top of the stack will be a dangling reference to the $B$. Now it is totally massed.