昨天刚看完BlockingQueue觉得好高级啊,今天扫到1.7就发现了升级版。。。。

如果对内容觉得不够充分,可以去看http://www.cs.rochester.edu/u/scott/papers/2009_Scherer_CACM_SSQ.pdf

就是作者的论文啦,纯英文。。。比较难啃,但是我觉得逻辑上比看代码容易理解,其实代码什么u啊h啊看得很混

LinkedTransferQueue

起源: 我觉得是这样的,之前的BlockingQueue是对 读取 或者 写入 锁定整个队列,所以在比较繁忙的时候,各种锁比较耗时

而当时有一个SynchronizedQueue其实不能叫Queue,因为只能放一个物件,要么有一个物件在等人拿,要么有一个空等人放

根据这个原理,诞生了LinkedTransferQueue,利用CompareAndSwap进行一个无阻塞的队列,针对每一个操作进行处理样大家就不用抢得那么辛苦了

数据结构

在类的内部保持着一个栈,基本单位是node,根据 hasData区分里面有两种元素,要么是 Data 要么是 Reservation,不会同时存在

并且有一个变量head指向最前面的node,没东西则是null

Node

{

  isData    是不是数据,是的话item放具体东西

  item   如果不是数据则为null

  next   下一个节点

  waiter  如果不是数据则是reservation,有一个线程在等待

}

过程:

整个存取过程分成两部分

1:MATCH(原节点,新节点)

for (;;) {                            // restart on append race

            for (Node h = head, p = h; p != null;) { // 如果头结点为空则跳过,非空进去找第一个可用节点
boolean isData = p.isData;
Object item = p.item;
if (item != p && (item != null) == isData) { // 判断原节点可用性,如data的item应该是数值,如果是null则表明用过了
if (isData == haveData) // 两个节点是相同类型,不用match了,去下一步
break;
if (p.casItem(item, e)) { // 节点不同类型,match成功,更改原节点item,表明不可用
for (Node q = p; q != h;) {//什么,我居然不是head节点了?我要让它指向我!
Node n = q.next; // update by 2 unless singleton
if (head == h && casHead(h, n == null ? q : n)) {
h.forgetNext();
break;
} // advance and retry
if ((h = head) == null ||
(q = h.next) == null || !q.isMatched())
break; // unless slack < 2
}
LockSupport.unpark(p.waiter);//根据原节点的类型,reservation则叫人收货,data则叫null收货
return LinkedTransferQueue.<E>cast(item);//根据原节点的类型,reservation则返回null,data则返回数据
}
}
Node n = p.next;//下一个节点
p = (p != n) ? n : (h = head); // Use head if p offlist
}

  重点是找出第一个可用节点,如果是null则跳过,如果与进来的节点相同(本来就有data,还放data)也跳过,如果不同(本来是data,现在是reservation,返回data值 / 本来是reservation,现在是data,叫人来收货,返回reservation值=空)

2:处理节点

if (how != NOW) {                 // No matches available
if (s == null)
s = new Node(e, haveData);
Node pred = tryAppend(s, haveData);//尝试添加新node
if (pred == null)
continue retry; // 不成功则重试整个过程
if (how != ASYNC)
return awaitMatch(s, pred, e, (how == TIMED), nanos);//根据参数,等不等别人放数据,拿数据,等多久
}
return e; // not waiting

  MATCH失败了才会进入这个环节,把新节点放进栈内,并根据参数决定立刻返回或者等待返回

EXAMPLES

1:Head->Data    Input->Data

Match:      根据他们的属性 发现 cannot match ,因为是同类的

处理节点:   所以把新的data放在原来的data后面,然后head往后移一位,Reservation同理

HEAD=DATA->DATA

2:Head->Data    Input->Reservation  (取数据)

Match:      成功match,就把Data的item变为reservation的值(null,有主了),并且返回数据。

处理节点:  没动,head还在原地

HEAD=DATA(用过)

3:Head->Reservation  Input->Data(放数据)

Match:       成功match,就把Reservation的item变为Data的值(有主了),并且叫waiter来取

处理节点:  没动

HEAD=RESERVATION(用过)

总结:LinkedTransferQueue通过CAS尝试放入data或增加reservation。

消耗小于把整个队列锁掉,但是在并发特别高的情况下大家抢着尝试一样会影响速度

至于为什么跨过了1.6到1.7这个类才出现我觉得有点神奇

简单用法介绍------------------------------------------------------------------------------------------------------

存:

put();   放元素进去队列,注意队列是可以无限长的

add();   同上

transfer();  这个是重点,如果队列中有人发现有人在等,则直接给那个人(有一个参数waiter指定了在等的线程)

如果没人在等,就放进队列

取:

poll();  立即返回,如果没有元素就是空

take(); 如果没有元素,那就等

PS:最好是用poll然后自己处理空的状况,如果全是take然后又迟迟没有东西,那就一堆内存在等了。

JAVA 1.7并发之LinkedTransferQueue原理理解的更多相关文章

  1. java的classLoader原理理解和分析

    java的classLoader原理理解和分析 学习了:http://blog.csdn.net/tangkund3218/article/details/50088249 ClassNotFound ...

  2. Java并发之AQS原理解读(三)

    上一篇:Java并发之AQS原理解读(二) 前言 本文从源码角度分析AQS共享锁工作原理,并介绍下使用共享锁的子类如何工作的. 共享锁工作原理 共享锁与独占锁的不同之处在于,获取锁和释放锁成功后,都会 ...

  3. Java并发之AQS原理解读(二)

    上一篇: Java并发之AQS原理解读(一) 前言 本文从源码角度分析AQS独占锁工作原理,并介绍ReentranLock如何应用. 独占锁工作原理 独占锁即每次只有一个线程可以获得同一个锁资源. 获 ...

  4. Java并发之AQS原理解读(一)

    前言 本文简要介绍AQS以及其中两个重要概念:state和Node. AQS 抽象队列同步器AQS是java.util.concurrent.locks包下比较核心的类之一,包括AbstractQue ...

  5. 【java并发编程艺术学习】(三)第二章 java并发机制的底层实现原理 学习记录(一) volatile

    章节介绍 这一章节主要学习java并发机制的底层实现原理.主要学习volatile.synchronized和原子操作的实现原理.Java中的大部分容器和框架都依赖于此. Java代码 ==经过编译= ...

  6. Java并发机制的底层实现原理之volatile应用,初学者误看!

    volatile的介绍: Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现 ...

  7. 大白话说Java泛型(二):深入理解通配符

    文章首发于[博客园-陈树义],点击跳转到原文<大白话说Java泛型(二):深入理解通配符> 上篇文章<大白话说Java泛型(一):入门.原理.使用>,我们讲了泛型的产生缘由以及 ...

  8. Java 常用数据结构对象的实现原理 集合类 List Set Map 哪些线程安全 (美团面试题目)

    Java中的集合包括三大类,它们是Set.List和Map, 它们都处于java.util包中,Set.List和Map都是接口,它们有各自的实现类. List.Set都继承自Collection接口 ...

  9. Java中char和String 的深入理解 - 字符编码

    开篇 https://blog.csdn.net/weixin_37703598/article/details/80679376 我们并不是在写代码,我们只是将自己的思想通过代码表达出来! 1 将思 ...

随机推荐

  1. Android View的生命周期

    View生命周期相关方法 View是什么?官方源码注释中的定义:这个类是用户接口的基础构件.View表示屏幕上的一块矩形区域,负责绘制这个区域和事件处理. View是所有widget类的基类,Widg ...

  2. DP问题如何确定状态

    DP问题如何确定状态 一.dp实质 动态规划的实质就是通过小规模的同类型的问题来解决题目的问题. 所以有一个dp数组来储存所有小规模问题的解. 所以确定状态也就是缩小问题规模. 我们求解问题的一般规律 ...

  3. Maven的生命周期阶段

    一.Maven的生命周期 Maven的生命周期就是对所有的构建过程进行抽象和统一.包含了项目的清理.初始化.编译.测试.打包.集成测试.验证.部署和站点生成等几乎所有的构建步骤. Maven的生命周期 ...

  4. Java中使用Log的方法

    一.java自带log:java.util.logging.Logger使用三步曲 public class HelloLogWorld { private static String name = ...

  5. java正则表达式(基础篇)

    1.数量表达 {n} :出现n次 {m,n}:最少出现m次,最多出现n次 *:表示出现>=0次,相当于{0,} +:表示出现>=1次,相当于{1,} ?:表示出现1次或0次 |:左右两边正 ...

  6. 【Demo】CSS3 2D转换

    2D转换transform 2D变换方法: translate() 根据左(X轴)和顶部(Y轴)位置给定的参数,从当前元素位置移动. div { transform: translate(50px,1 ...

  7. iOS-沙盒路径

    iphone沙箱模型的有四个文件夹,分别是什么,永久数据存储一般放在什么位置,得到模拟器的路径的简单方式是什么.documents,tmp,app,Library.(NSHomeDirectory() ...

  8. 【专题】区间dp

    1.[nyoj737]石子合并 传送门:点击打开链接 描述    有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这 ...

  9. Struts07---访问servlet的API

    01.创建登录界面 <%@ page language="java" import="java.util.*" pageEncoding="UT ...

  10. Activiti 教程

    Activiti入门教程:http://blog.csdn.net/column/details/activitizhou.html Activiti 5.15 用户手册:http://www.cnb ...