Java中使用AtomicStampedReference

时间:2015-07-30 02:49:20

标签: java concurrency

所以我首先要说的是这是一项任务,对我需要构建的队列有一些限制:

  1. 这是无限的。

  2. 不允许使用锁定机制(没有synchronizedReentrantLock等){甚至不能模拟像CompareAndSet这样的东西}。

  3. 必须实施Michael and Scott's算法。

  4. 当然,我无法剔除ConcurrentLinkedQueue的Java源代码。

  5. 这是我到目前为止所做的事情(遗漏了):

    public class LockFreeQueue<T> implements MyQueue<T>
    {
        private class Node<R>
        {
            public final R value;
            public volatile AtomicReference<Node<R>> next;
    
            public Node()
            {
                value = null;
                next = new AtomicReference<Node<R>>(null);
            }
    
            public Node(R v)
            {
                value = v;
                next = new AtomicReference<Node<R>>(null);
            }
        }
    
        volatile AtomicStampedReference<Node<T>> head = new AtomicStampedReference<Node<T>>(new Node<T>(), 0);
        volatile AtomicStampedReference<Node<T>> tail = head;
        AtomicInteger count = new AtomicInteger(0);
    
        public boolean enq(T value)
        {
            Node<T> node = new Node<T>(value);
    
            while (true)
            {
                Node<T> tempTail = tail.getReference();
                int tailCount = tail.getStamp();
                Node<T> next = tempTail.next.get();
                if (tempTail == tail.getReference())
                {
                    if (null == next)
                    {
                        if(tempTail.next.compareAndSet(null, node))
                        {
                            // Problem on this line:
                            tail.compareAndSet(tempTail, node, tailCount, count.incrementAndGet());
                            return true;
                        }
                    }
                    else
                    {
                        tail.compareAndSet(tempTail, next, tailCount, count.incrementAndGet());
                    }
                }
            }
        }
    ...
    }
    

    现在,在大多数情况下,这遵循this IBM article中的代码。特别是,它遵循Listing 4. Insertion in the Michael-Scott nonblocking queue algorithm中的代码。我的代码和文章中的代码所展示的问题是,当尾部的引用转向新的尾部时,它对头部也是如此。这样做当然是因为它改变了被引用的Node,而不是实际的引用,tailhead的引用是相同的。

    我还发现了a different solution,但此代码的主要问题是它使用synchronized,即使它只是模拟CAS操作。

    就Java的ConcurrentLinkedQueue而言,我注意到他们使用AtomicReferenceUpdater,这似乎是唯一可行的方法。不过,这里的问题是我的代码开始看起来非常接近Java,而且我不想成为剽窃的停靠点(或更糟糕的!)。

    AtomicReferenceUpdater是我前进的唯一途径,还是我可以做的其他事情?

    最后一点:

    • Node是我自己的完全捏造,所以它可以变成任何它需要的东西。

    修改

    Ben Manes提到不需要担心垃圾收集语言中的ABA问题。对于那些对此感兴趣的人,有this article这是一个很好的阅读。重要的部分:

      

    在垃圾收集语言中,这不是问题。为什么?因为在观察包含指向结构的指针的线程释放它们之前,无法为新对象回收节点的内存。

0 个答案:

没有答案