基于单链表实现一个非阻塞的栈
Posted Dream_it_possible!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于单链表实现一个非阻塞的栈相关的知识,希望对你有一定的参考价值。
栈是最简单的单链表结构,我们可以通过从单链表的尾插节点、从尾部取出节点实现栈的存取元素。
我们都知道CAS可以保证操作的原子性和可见性,AtomicReference能和volatile关键字有同样的效果,因此可以结合AtomicReference+CAS实现Push和PoP元素操作的可见性和原子性,每次Push和Pop的时候更新新的Head, 如果有其他线程干扰的情况下,那么修改操作失败。
package com.example.jucdemo.stack;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
* 基于单链表实现非阻塞的栈结构
* AtomicReference+CAS
*
* @param <E>
*/
public class ConcurrentStack<E>
AtomicReference<Node<E>> top = new AtomicReference<>();
/**
* 通过CAS操作,每次取出栈顶元素,取出完毕后,再设置下一个节点为栈顶元素
*
* @param item
*/
public void push(E item)
//设置一个新的Node节点
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do
oldHead = top.get();
newHead.next = oldHead;
while (!top.compareAndSet(oldHead, newHead));
System.out.println("push的值为" + item.toString() + ",得到的链表为:" + newHead.traverse());
public E pop()
Node<E> newHead;
Node<E> oldHead;
do
oldHead = top.get();
if (oldHead == null)
return null;
newHead = oldHead.next;
while (!top.compareAndSet(oldHead, newHead));
if (newHead != null)
System.out.println("pop的值为" + oldHead.item.toString() + ",得到的链表为:" + newHead.traverse());
return oldHead.item;
static class Node<E>
private final E item;
private Node<E> next;
public Node(E item)
this.item = item;
public String traverse()
String current = this.item.toString();
return this.next == null ? current : current + "->" + this.next.traverse();
private static ConcurrentStack<Integer> stack = new ConcurrentStack<>();
public static void main(String[] args)
Thread t1 = new Thread(new Task());
Thread t2 = new Thread(new Task());
Thread t3 = new Thread(new Task());
Thread t4 = new Thread(new Task());
Thread t5 = new Thread(new Task());
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
try
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
catch (InterruptedException e)
e.printStackTrace();
System.out.println();
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
private volatile static AtomicInteger i = new AtomicInteger(0);
static class Task implements Runnable
@Override
public void run()
Integer value = i.getAndIncrement();
System.out.println(Thread.currentThread().getName() + "push数据:" + value);
stack.push(value);
打印结果:
Thread-0push数据:0
Thread-3push数据:3
Thread-2push数据:2
Thread-1push数据:1
Thread-4push数据:4
push的值为0,得到的链表为:0
push的值为2,得到的链表为:2->1->4->0
push的值为1,得到的链表为:1->4->0
push的值为4,得到的链表为:4->0
push的值为3,得到的链表为:3->2->1->4->0
pop的值为3,得到的链表为:2->1->4->0
3
pop的值为2,得到的链表为:1->4->0
2
pop的值为1,得到的链表为:4->0
1
pop的值为4,得到的链表为:0
4
0
null
Process finished with exit code 0
从打印结果中,我们可以发现,插入的顺序和取出的元素顺序是正好相反的。
参考: <<Java并发编程实战>>
以上是关于基于单链表实现一个非阻塞的栈的主要内容,如果未能解决你的问题,请参考以下文章