Phaser是java7版本添加的一个同步工具,相比CyclicBarrier、CountDownLatch、Semaphore等同步工具,Phaser使用更灵活而且可复用(CyclicBarrier也可复用),Phaser包含几个动作:

register:给Phaser增加parties,并且可以通过deRegister减少总parties(CyclicBarrier、CountDownLatch、Semaphore等工具不具备这种灵活性)。

arrive:parties已到达。

awaitAdvance:在所有parties都到达之前当前线程处于挂起等待状态,当所有parties都已到达之后线程被唤醒并且Phaser年龄增加,未到达parties数还原,Phaser复用。

Phaser通过status字段来实现同步逻辑,status是一个64位的long变量,它有包含了四个维度的语义:

1、第0-15位,当前未到达的parties,调用arriveXXX时,该值-1,调用register时+1;

2、第16-31位,当前总parties,调用register时+1,deRegister时-1;

3、第32-62位,phase,即Phaser的年龄,当未到达的parties减到0(即所有parties已到达)时,phase自动加1,并且把16-31位的parties数复制到0-15位,从而该Phaser可以继续复用;

当Phaser的parties数比较大的高并发场景下,Phaser的status变量的竞争会非常激烈,register、arrive等操作发起的CAS操作预测将会大概率失败导致大量CAS操作被重复调用,增加CPU开销。可以通过构造Phaser分层树的方式来分离竞争,子Phaser第一次register时,把该子Phaser注册到父Phaser,当子Phaser所有parties都已经arrive时,把它从父Phaser中反注册。

当根Phaser的所有子Phaser的parties都已经arrive时,整个Phaser树升级phase递增,通过这种方式,所有的arrive、register操作在子Phaser进行就可以,根Phaser只需负责Phaser的升级,这样可以把部分对status的访问修改分离到子Phaser中,通过分散竞争点提高Phaser的吞吐量。

下面示例代码就把9个parties分散到了两个子Phaser中:

注册parties时,主要做的事情就是修改status变量的parties部分和unarrive部分,同时也可以看到,在第一注册时,调用了代码parent.doRegister(1),注册一次party到父Phaser。

线程触发arrive操作时,如果当前Phaser的所有parties都已经arrive,那么调用一次parent.doArrive(1),如果所有parties都已经arrive并且当前Phaser时根Phaser,说明该Phaser可以升级,phase值加1,唤醒由于调用了awaitXXX被阻塞的线程。在升级时有个onAdvance回调可以让调用者终止Phaser。

触发Phaser的awaitAdvance时,Phaser的await操作不会直接挂起线程,会先对根Phaser的status自旋检查,检查phase是否发生了变化,自旋了若干次(这个数值跟当前CPU的核心数有关)之后如果phase还未发生变化则挂起线程,这样做的目的是挂起线程会造成上下文切换,如果Phaser在很短的时间内就升级了,那么这样就减少了上下文切换次数提高CPU吞吐量,但是自旋检查也会造成CPU消耗,所以也不能一直自旋。在上面的arrive方法中可以看到,当所有parties都arrive之后修改phase值加1,所以internalAwaitAdvance方法中的while条件将不成立,跳出循环唤醒所有等待的线程。下面是唤醒线程的方法:

这个方法相对简单,就是有一点需要注意的是:有两个线程等待队列头节点分别是evenQ和oddQ,这是因为在并发场景下,老Phaser所有parties都已经arrive之后等待队列的线程正在被唤醒,但是此时又有线程在对升级后的Phaser调用了await,如果只有一个队列的话那么此时队列头结点出现激烈的竞争,所以这里面把相邻的年龄的Phaser等待线程放在两个队列中可以达到分离竞争的目的。

phaser java_java并发编程:Phaser同步工具原理相关推荐

  1. Java高并发编程:同步工具类

    内容摘要 这里主要介绍了java5中线程锁技术以外的其他同步工具,首先介绍Semaphore:一个计数信号量.用于控制同时访问资源的线程个数,CyclicBarrier同步辅助类:从字面意思看是路障, ...

  2. Java 并发编程之同步工具类闭锁 CountDownLatch

    Java 同步工具类CountDownLatch相当于一个计数器,假设一个方法,等待一个计数器从初始值5变为0,每使用一次countdown()方法,计数器的值减少1,当计数器的值为0时,触发某件事. ...

  3. Java 并发编程之同步工具类 Exchanger

    Exchanger 交换器,用于两个线程之间交换数据. 线程1调用exchange()方法,然后进行线程阻塞,等待线程2调用exchange()方法交换数据,线程2调用exchange()方法后,两个 ...

  4. Java 并发编程之同步工具类栅栏 CyclicBarrier

    CyclicBarrier 用来阻塞一组线程,等待线程完成后才开始某件事情. 例如,开启5个线程,每个线程使用await方法开始阻塞,等待5个线程都完成,才开始执行await方法后面的代码. publ ...

  5. Java 并发编程之同步工具类信号量 Semaphore

    Semaphore 可以理解为一个阈值,正在进行的操作数量不能超过此阈值,可以用来限制资源的访问,或者控制某个队列中对象的个数,也就是控制同时执行的线程的数量. 主要有acquire,release两 ...

  6. python 线程同步_Python并发编程-线程同步(线程安全)

    Python并发编程-线程同步(线程安全) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 线程同步,线程间协调,通过某种技术,让一个线程访问某些数据时,其它线程不能访问这些数据,直 ...

  7. phaser java_Java 7的并发编程-Phaser

    Java 7的并发包中推出了Phaser,其功能跟CyclicBarrier和CountDownLatch有些重叠,但是提供了更灵活的用法,例如支持动态调整注册任务的数量等.本文在Phaser自带的示 ...

  8. java虚拟机线程调优与底层原理分析_Java并发编程——多线程的底层原理

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

  9. Java并发编程—线程同步类

    原文作者:洲洋1984 原文地址:Java 并发包中的高级同步工具 Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提 ...

  10. Java并发编程 Synchronized及其实现原理

    Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法.Synchronized的作用主要有三个:(1)确保线程互斥的访问同步代码(2)保证共享变量的修改能够及时可见 ...

最新文章

  1. android monkey原理_Monkey与Appium的使用
  2. nginx动静分离和负载均衡
  3. C++ COM编程之什么是接口
  4. SAP 电商云 Spartacus UI 修改 Delivery Mode 触发的三个 HTTP 请求
  5. js br不生效_前端标注工具-AILabel.js
  6. Eclipse Java EE的tomcat使用小结
  7. cocos2dx 3.x(移动修改精灵坐标MoveTo与MoveBy)
  8. 网站的前期策划准备工作
  9. node.js 与 nvm安装教程
  10. 液晶接口系列——MIPI(三)DSI时序讲解与实际测试
  11. android studio 融云,融云 SDK 是否支持 AndroidX
  12. 基于CNN的人脸相似度检测
  13. 苹果平板重设id显示服务器出错,苹果一代平板电脑重设ID怎么?
  14. PDF怎么用免费软件转换成word?推荐个高性价比转换方法
  15. 【GameObject 类】 (四)SetActive 显示 / 隐藏游戏对象
  16. 用 Python 写了一个表白神器,照片隐藏表白话语!
  17. Element表格出现闪动问题
  18. 心跳服务1.0(Heart Rate Service 1.0)
  19. 如何绘制流程图?绘制流程图在线网站分享
  20. 论文评审最大流_2018年论文评审流程

热门文章

  1. manjaro配置输入法
  2. 郁金香java_郁金香搜索引擎的方案
  3. 《程序员的职业素养》读书笔记万字总结【建议收藏】
  4. Arduino 入门学习笔记5 按键控制激光发生器
  5. Deepest Root(dfs深度优先遍历)
  6. threejs的转场动画 (基于Tween实现)、平滑切换场景
  7. Flask Template ( 模板学习)
  8. selenium模拟破解京东滑块验证码
  9. CMD打开Git Bash
  10. 【c语言】(函数)利用麦克劳林公式求sinx,cosx,tanx