Node p = enq(node);
···
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))LockSupport.unpark(node.thread);// 唤醒节点上的线程return true;
···

通过enq放入同步队列了,他自己会慢慢的争抢锁,就像synchronize中的wait,为什么这里要进行一次unpark?

先看下判断条件。

ws>0,说明是1,是CANCELLED状态,!compareAndSetWaitStatus(p, ws, Node.SIGNAL)) 什么时候把前一个节点(enq(node);返回当前节点的前一个节点,也就是原来的tail)赋值为SIGNAL状态失败?就是前一个节点是CANCELLED的时候,好吧这两个好像是一个命题。

接着看为什么这里要进行一次unpakr?

10-12行的迷惑性就来源于此。实际上,就算去掉10-12行也是满足正确性要求的。因为线程T2释放锁后,依然会将从队头开始的第一个非取消节点唤醒,该节点会继续ConditionObject#await()中的工作(稍后回去分析)。10-12行是为了进一步提升性能,针对两种情况:

  • 如果插入node前,AQS内部等待队列的队尾节点就已经被取消,则满足wc > 0
  • 如果插入node后,AQS内部等待队列的队尾节点已经稳定,满足tail.waitStatus == 0,但在执行ws >
    0之后!compareAndSetWaitStatus(p, ws,
    Node.SIGNAL)之前被取消,则CAS也会失败,满足compareAndSetWaitStatus(p, ws,
    Node.SIGNAL) == false

这两种情况下,提前唤醒node能够在等待锁的同时,预先完成一部分ConditionObject#await()中无需同步的工作。这部分成本不能被轻易忽视,因为条件队列被应用最多的场景是高并发,大量线程累加起来的成本是很可观的。
链接:https://www.jianshu.com/p/a932c184db52

  1. 在从condition队列到同步队列之前,tail节点被取消了

  2. 在从condition队列到同步队列之后,tail节点没被取消,执行完ws > 0
    之后,这段时间,被取消了?就通过!compareAndSetWaitStatus(p, ws, Node.SIGNAL)再判断一下

    这个时候偷偷的提前执行一波,就算不提前执行,AQS队列会不断的把取消节点取消掉,最终还是被unpark的。
    总的意思就是为了提升性能,没有这里也是合理的。

Condition中的transferForSignal()方法的不解相关推荐

  1. python中文读音ndarray-numpy中的ndarray方法和属性详解

    NumPy数组的维数称为秩(rank),一维数组的秩为1,二维数组的秩为2,以此类推.在NumPy中,每一个线性的数组称为是一个轴(axes),秩其实是描述轴的数量.比如说,二维数组相当于是一个一维数 ...

  2. junit4 assert类中的assert方法总结

    junit中的assert方法全部放在Assert类中,总结一下junit类中assert方法的分类. 1.assertTrue/False([String message,]boolean cond ...

  3. 如何去掉DataTable中的重复行(新增.net 2.0中最新解决方法---简便)

    .net 1.1中的解决方法(转) 1建立一个DataSetHelper类(DataSetHelper.cs) public class DataSetHelper ...{     public D ...

  4. 数组中的filter方法_数组filter()方法以及JavaScript中的示例

    数组中的filter方法 JavaScript filter()方法 (JavaScript filter() method) filter() method is used to returns a ...

  5. 关于java中线程yield()方法问题

    关于java中线程yield()方法问题 问题一: 我知道yield是用来休眠当前线程,但我查看了资料,又说其不会释放锁,所以我就不解了,其明明会将cpu资源给其他线程,那它不释放锁,其他线程有怎么获 ...

  6. 自定义附加属性在XAML中的表示方法以及绑定的注意事项

    在XMAL中的表示方法 必须把在XAML中导入CLR名称空间 <UserControlxmlns="http://schemas.microsoft.com/winfx/2006/xa ...

  7. 关于学习java函数式接口Function中的apply方法的一些感悟

    起因是这样的,学习函数式编程的时候学到了Function接口,对于其中的apply方法感到不解,下面贴上我的不解代码 在这里插public class Function接口 {public stati ...

  8. MIT18.065 数据分析、信号处理和机器学习中的矩阵方法-学习笔记

    文章目录 MIT18.065 数据分析.信号处理和机器学习中的矩阵方法 Lecture 1 The Column Space of A Contains All Vectors Ax A=CR A=C ...

  9. java中list中sublist_Java 中 List.subList() 方法的使用陷阱

    前言 本文原先发表在我的 iteye博客: http://clevergump.iteye.com/admin/blogs/2211979, 但由于在 iteye发表的这篇文章的某些渲染曾经出现过一些 ...

最新文章

  1. java怎么表示log2_Java程序员修炼之道 之 Logging(2/3) - 怎么写Log
  2. iOS 2D绘图详解(Quartz 2D)之路径(点,直线,虚线,曲线,圆弧,椭圆,矩形)
  3. 打造一个宇宙 星系模拟产生对宇宙进化惊人见解
  4. VTK:Utilities之AnimationScene
  5. 开源 | App 开发神仙工具:帮你抓 Bug
  6. Linux ping不通百度的解决方法
  7. 浸会大学计算机专业硕士排名2019,2019软科世界大学学术排名香港浸会大学排名第701-800...
  8. java银行叫号模拟系统_Java 模拟银行叫号机
  9. 全屏使用swiper.js过程中遇到的坑
  10. 【Python】Python3.7.3 - memoization 结果缓存记忆程序设计优化技术
  11. Android 之神 Jake Wharton 从 Square 离职!
  12. 计算机中内存存储器最小单位,计算机中存储容量的最小单位和最基本单位是什么?...
  13. psd导出jpg太大_【设计】PSD导出JPG文件非常大解决办法
  14. python ttk style,如何改变ttk.progressBar颜色在python
  15. 名字里有计算机里没有的字体大小,公安13000字的庞大字库打不出这些字 五市民名字让电脑“犯晕”...
  16. Java main是什么_java中的public static void main是什么意思
  17. 设计模式(一)设计模式的分类与区别
  18. python通过接口判断公共节假日
  19. 封神台靶场-尤里的复仇-第二章
  20. 中控门禁无法添加设备,提示表结构不存在或接收超时

热门文章

  1. Linux 将文件打包、压缩并分割成指定大小
  2. 面试题25: 合并两个排序的链表
  3. 洛谷 P2596 [ZJOI2006]书架 (splay)
  4. ACM数论之旅2---快速幂,快速求a^b
  5. python之路_计算机编码及运算符介绍
  6. [NOIP2006] 数列
  7. 1 客户端性能--浏览器页面处理
  8. Michael-Scott非阻塞队列(lock-free)算法的C实现
  9. selenium(2.4.0)中不能导出web drive 代码
  10. 4 系统的 CPU 使用率很高,但为啥却找不到高 CPU的应用?