ConcurrentLinkedQueue的原理以及CAS机制在其中的应用
来源:互联网 发布:kindle电子书编辑软件 编辑:程序博客网 时间:2024/04/19 21:19
ConcurrentLinkedQueue是一个线程安全队列,区别于阻塞算法的锁机制,它使用了基于CAS机制的非阻塞算法。
基本概念介绍:
队列:通常(但并非一定)以 FIFO(先进先出)的方式排序各个元素。
接口Queue
接口quque中的方法可以分为三类添加队列尾元素 boolean add(E e)与boolean offer(E e)add结果只能为返回true(成功插入)或抛出异常(不成功),根据异常类型(IllegalStateException)才能看出是否由于对列容量限制offer结果返回true(成功插入)或返回false(容量限制)或抛出异常获取队列头但不移除 E element() 与 E peek()区别在于当队列为空时 elemnet()方法抛出异常peek方法返回null获取对列头并移除remove() 与 poll()区别在于队列为空时 remove()方法抛出异常poll方法返回null
之前文章说明过CAS机制的依据(硬件层面的是实现):http://blog.csdn.net/do_finsh/article/details/78773573
以及大体java.util.concurrent包下的类实现的共同点:
- .声明共享变量为volatile;(没有原子性,有可见性)
- 使用CAS的原子条件更新来实现线程之间的同步;
- 配合以volatile的读/写和CAS所具有的volatile读和写的内存语义来实现线程之间的通信。
现在具体说明一下ConcurrentLinkedQueue中的应用
首先出现了一个私有静态类Node
这个Node类中出现了UNSAFE类,节点类Node< E> 通过UNSAFE类的方法,进行CAS操作。大致了解一下
UNSAFE类的方法
// 获取f在堆内存的偏移地址 public native long objectFieldOffset(Field f); // 获取静态f在堆内存的偏移地址 public native long staticFieldOffset(Field f); // 原子的更改offset地址的变量。如果变量的值为expected,并成功替换为x 返回true CAS操作 public final native boolean compareAndSwapObject(Object o, long offset, Object expected,Object x); // 将offset地址的值替换为x,并且通知其他线程。因为有Volatile,与putObject类似 public native void putObjectVolatile(Object o, long offset, Object x); // 获取地址为offset 的值 public native Object getObjectVolatile(Object o, long offset) /** * Version of {@link #putObjectVolatile(Object, long, Object)} * that does not guarantee immediate visibility of the store to * other threads. This method is generally only useful if the * underlying field is a Java volatile (or if an array cell, one * that is otherwise only accessed using volatile accesses). */public native void putOrderedObject(Object o, long offset, Object x);
节点类Node
private static class Node<E> { volatile E item; // volatile声明 volatile Node<E> next; // volatile声明 // 构造方法 在地址itemOffset处, 值替换为item Node(E item) { UNSAFE.putObject(this, itemOffset, item); } // CAS操作:比较并交换,原子的更改itemOffset地址的变量。如果变量的值为cmp,并成功替换为val 返回true boolean casItem(E cmp, E val) { return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); } // 将nextOffset地址的值替换为x void lazySetNext(Node<E> val) { UNSAFE.putOrderedObject(this, nextOffset, val); } // CAS操作:比较并交换,原子的更改nextOffset地址的变量。如果变量的值为cmp,并成功替换为val 返回true boolean casNext(Node<E> cmp, Node<E> val) { return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE; private static final long itemOffset; private static final long nextOffset; /** * 静态代码块,获取itemOffset和nextOffset */ static { try { UNSAFE = sun.misc.Unsafe.getUnsafe(); Class k = Node.class; itemOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("item")); nextOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("next")); } catch (Exception e) { throw new Error(e); } } }
ConcurrentLinkedQueue的常用方法offer(E e);
public boolean offer(E e) { checkNotNull(e); //创建一个入队节点 final Node<E> newNode = new Node<E>(e); // 死循环,直到return ture // 创建一个指向tail节点的引用t // p用来表示尾结点 for (Node<E> t = tail, p = t;;) { // 获取p的下一节点 Node<E> q = p.next; // 如果q为空,说明p是尾节点 if (q == null) { // p是尾节点,把e放入p节点之后,CAS操作(原子性操作),成功,跳出循环 if (p.casNext(null, newNode)) { if (p != t) // 如果tail不是尾节点则将入队节点设置为tail。如果失败了,那么说明有其他线程已经把tail移动过 casTail(t, newNode); return true; } } // 如果p节点等于p的next节点,则说明p节点和q节点都为空,表示队列刚初始化,所以返回 else if (p == q) p = (t != (t = tail)) ? t : head; else //p有next节点,表示p的next节点是尾节点,则需要重新更新p后将它指向next节点 //此步判断非原子性操作t != (t = tail) p = (p != t && t != (t = tail)) ? t : q; } }
阅读全文
0 0
- ConcurrentLinkedQueue的原理以及CAS机制在其中的应用
- 背单词,及工程原理在其中的应用
- ConcurrentLinkedQueue的实现原理分析
- ConcurrentLinkedQueue的实现原理分析
- ConcurrentLinkedQueue的实现原理分析
- ConcurrentLinkedQueue的实现原理分析
- ConcurrentLinkedQueue的实现原理分析
- ConcurrentLinkedQueue的实现原理分析
- ConcurrentLinkedQueue 的实现原理分析
- ConcurrentLinkedQueue的实现原理分析
- ConcurrentLinkedQueue的实现原理分析
- (java并发)CAS操作原理以及Atomic的原理
- ConcurrentLinkedQueue的实现原理和源码分析
- jdk1.8中ConcurrentLinkedQueue的实现原理
- ConcurrentLinkedQueue的实现原理和源码分析
- Java的CAS机制
- AtomicInteger的CAS原理
- AtomicInteger的CAS原理
- 欢迎使用CSDN-markdown编辑器
- 关于Go的闭包、匿名函数和defer的结合使用案例分析
- Web网页自定义分享的标题、内容和图片
- 我理解的javascrpit闭包
- Windows下安装github
- ConcurrentLinkedQueue的原理以及CAS机制在其中的应用
- 深度学习这些坑你都遇到过吗?
- VB .Net基本控件的绑定跟赋值
- 单相PWM交流调压电路设计
- PHP中添加HTML代码的三种方法
- ArcGIS Engine中刷新视图总结
- Ubuntu 16.04安装Eclipse
- 机器视觉专栏(三)图像的几何变换
- 在windows配置Apache httpd代理服务器