The deque is a doublely ended queue. Insertion and deletion can happen at both ends. Internally, this deque is represented as a doubly linked list. For each deque, there is an anchor object which comprise of 2 pointers and 1 flag. The pseudo-code is as shown below:
Anchor{The key idea of this deque algorithm is to automatically updating this anchor field when deque is being changed. An anchor object occupies more than a machine word. Until now, there is no portable way to automatically updating such an "wide" object in Java. Actually, we don't need a wider "CAS" for implementing lock free deque. The idea is simple:
Node left, right;
enum {STABLE, LEFT, RIGHT} flag;
} anchor;
- We make Anchor immutable and use an AtomicReference to wrap it
- Whenever we want to update an anchor, we create a new Anchor object and use AtomicReference.compareAndSwap() to update the anchor automatically.
Besides, there is an object allocated for each updating. Will this be a big overhead? Since memory allocation in Java is relatively cheaper than other languages, this approach works well when frequency is moderate. Performance charts are shown below:
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL89lQ9yTQ6QHjK1GxWoqjchyphenhyphenVnI2v8Qi7AOdSAfFkLdI6TZwxvMKuWUva5Eg58W2itFd3HH91xGWycmy9tYWIYcMFEnyNTUVWcLAde2riDhr7OjGR9fQ20ToUiohigf0nOkSEyqn7iUWJ/s400/LinkedBlockingDeque_LockFreeDeque_read99write1.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglDMTSHPDy11ako0Oci8Unm2_Ohq90iD72enQcq6cxG_EHi1Yi1StzQYPi3kKZPpA9I2F4DnXURLha9OALuXsTqLrrGQXa94Y0tKfYF2zx9R7ml6pxNIWFpBUaAAaETg4PkMENTn5EKJo8/s400/LinkedBlockingDeque_LockFreeDeque_read95write5.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAz20y8_Ex15LrmXb8JAknpgPjGQA6S7-zozxZ31hfUwpB0qnlIsHIEAZmBbRIu-bIOl7GlGon9ZWWRYgT_QhVvCS0Nyg7_RyWlApN1EMqoFbAmOeLxdrgeLLtnIvP50-i-fSm1cl6KDxk/s400/LinkedBlockingDeque_LockFreeDeque_read75write25.png)
This deque is not completely compatible with standard JDK API. For example, it doesn't support element deletion by iterator.remove(). This is normal to Amino lock-free components. To implement such an unusual method for deque, performance of other frequently used methods such as addFirst()/pollFirst()/addLast()/pollLast() will become much slower than before. That's the reason why Amino library choose not to support such methods. I personally don't think it's a big problem. After all, if a data structure supports deletion in the middle, can it still be called a deque/queue/stack?
No comments:
Post a Comment