JDK中的并发框架提供的另外一个优秀机制是锁获取超时的支持,当大量线程对某一锁竞争时可能导致某些线程在很长一段时间都获取不了锁,在某些场景下可能希望如果线程在一段时间内不能成功获取锁就取消对该锁的等待以提高性能,这时就需要用到超时机制。在JDK1.5之前并没有对此支持,当时的并发控制职能通过JVM内置的synchronized关键词实现锁,但对一些特殊要求却力不从心,例如超时取消控制。JDK1.5开始引入并发工具完美解决了此问题,JDK对并发线程开始提供超时的支持。
为了更精确地保证时间间隔统计的准确性,实现时使用了System.nanoTime()更为精确的方法,它能精确到纳秒级别。超时机制的思想就是在不断进行锁竞争的同时记录竞争的时间,一旦时间段超过指定的时间则停止轮询直接返回,返回前对等待队列中对应节点进行取消操作。往下看实现的逻辑,
if(尝试获取锁失败) { long lastTime = System.nanoTime();
创建node
使用CAS方式把node插入到队列尾部
while(true){
if(尝试获取锁成功 并且 node的前驱节点为头节点){
把当前节点设置为头节点
跳出循环
}else{
if (nanosTimeout <= 0){
取消等待队列中此节点
跳出循环
}
使用CAS方式修改node前驱节点的waitStatus标识为signal
if(修改成功)
if(nanosTimeout > spinForTimeoutThreshold)
阻塞当前线程nanosTimeout纳秒
long now = System.nanoTime();
nanosTimeout -= now - lastTime;
lastTime = now;
}
}


上面正在锁的获取逻辑中添加超时处理,核心逻辑是不断循环减去处理的时间消耗,一旦小于0就取消节点并跳出循环,其中有两点必须要注意,一个是真正的阻塞时间应该是扣除了竞争入队的时间后剩余的时间,保证阻塞事件的准确性,我们可以看到每次循环都会减去相应的处理时间;另外一个是关于spinForTimeoutThreshold变量阀值,它是决定使用自旋方式消耗时间还是使用系统阻塞方式消耗时间的分割线,JDK并发工具包作者通过测试将默认值设置为1000ns,即如果在成功插入等待队列后剩余时间大于1000ns则调用系统底层阻塞,否则不调用系统底层,取而代之的是仅仅让之在Java应用层不断循环消耗时间,属于优化的措施。

至此,JDK实现在获取锁的过程中提供了超时机制,超时的支持让Java在并发方面提供了更完善的机制,更多的并发策略满足开发者更多需求。


====广告时间,可直接跳过====

鄙人的新书《Tomcat内核设计剖析》已经在京东预售了,有需要的朋友可以到https://item.jd.com/12185360.html进行预定。感谢各位朋友。

=========================


欢迎关注:


更多相关文章

  1. android 百度地图路线规划去掉节点图标
  2. Android 时间日期选择器的用法
  3. Android时间日期类小结
  4. android 命令修改时间或程序修改系统时间
  5. 在服务中设置服务重复时间
  6. android init进程分析 ueventd — 设备节点的创建、固件更新过
  7. ffmpeg从视频中提取帧时间戳
  8. js实现把整数秒转化为"hh:mm:ss"的时间格式.
  9. Java获得文件的创建时间(精确到秒)

随机推荐

  1. 面向忙碌开发者的 Android
  2. rk3288 android 7.1 串口使用
  3. Android(安卓)Hugo
  4. ViewGroup常用布局操作
  5. Android 输入框限制字符输入数
  6. android 在surface上显示YUV 笔记
  7. 转:Android 开发技巧杂集
  8. Android应用开发中如何进行单元测试
  9. android中wifi原理及流程分析
  10. Android Network Resources