LockSupport HotSpot里park/unpark的实现
每个java线程都有一个Parker实例,Parker类是这样定义的:
class Parker : public os::PlatformParker {
private:
volatile int _counter ;
...
public:
void park(bool isAbsolute, jlong time);
void unpark();
...
}
class PlatformParker : public CHeapObj<mtInternal> {
protected:
pthread_mutex_t _mutex [1] ;
pthread_cond_t _cond [1] ;
...
}
可以看到Parker类实际上用Posix的mutex,condition来实现的。
在Parker类里的_counter字段,就是用来记录所谓的“许可”的。
当调用park时,先尝试直接能否直接拿到“许可”,即_counter>0时,如果成功,则把_counter设置为0,并返回:
void Parker::park(bool isAbsolute, jlong time) {
// Ideally we'd do something useful while spinning, such
// as calling unpackTime().
// Optional fast-path check:
// Return immediately if a permit is available.
// We depend on Atomic::xchg() having full barrier semantics
// since we are doing a lock-free update to _counter.
if (Atomic::xchg(0, &_counter) > 0) return;
如果不成功,则构造一个ThreadBlockInVM,然后检查_counter是不是>0,如果是,则把_counter设置为0,unlock mutex并返回:
ThreadBlockInVM tbivm(jt);
if (_counter > 0) { // no wait needed
_counter = 0;
status = pthread_mutex_unlock(_mutex);
否则,再判断等待的时间,然后再调用pthread_cond_wait函数等待,如果等待返回,则把_counter设置为0,unlock mutex并返回:
if (time == 0) {
status = pthread_cond_wait (_cond, _mutex) ;
}
_counter = 0 ;
status = pthread_mutex_unlock(_mutex) ;
assert_status(status == 0, status, "invariant") ;
OrderAccess::fence();
当unpark时,则简单多了,直接设置_counter为1,再unlock mutext返回。如果_counter之前的值是0,则还要调用pthread_cond_signal唤醒在park中等待的线程:
void Parker::unpark() {
int s, status ;
status = pthread_mutex_lock(_mutex);
assert (status == 0, "invariant") ;
s = _counter;
_counter = 1;
if (s < 1) {
if (WorkAroundNPTLTimedWaitHang) {
status = pthread_cond_signal (_cond) ;
assert (status == 0, "invariant") ;
status = pthread_mutex_unlock(_mutex);
assert (status == 0, "invariant") ;
} else {
status = pthread_mutex_unlock(_mutex);
assert (status == 0, "invariant") ;
status = pthread_cond_signal (_cond) ;
assert (status == 0, "invariant") ;
}
} else {
pthread_mutex_unlock(_mutex);
assert (status == 0, "invariant") ;
}
}
简而言之,是用mutex和condition保护了一个_counter的变量,当park时,这个变量置为了0,当unpark时,这个变量置为1。
值得注意的是在park函数里,调用pthread_cond_wait时,并没有用while来判断,所以posix condition里的"Spurious wakeup"一样会传递到上层Java的代码里。
if (time == 0) {
status = pthread_cond_wait (_cond, _mutex) ;
}
这也就是为什么Java dos里提到,当下面三种情况下park函数会返回:
- Some other thread invokes unpark with the current thread as the target; or
- Some other thread interrupts the current thread; or
- The call spuriously (that is, for no reason) returns.
LockSupport HotSpot里park/unpark的实现的更多相关文章
- 实现两线程的同步二(lockSupport的park/unpark)
1.使用LockSupport的part/unpark实现 package com.ares.thread; import java.util.concurrent.locks.LockSupport ...
- JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport的park/unpark)
一.前言 在多线程的场景下,我们会经常使用加锁,来保证线程安全.如果锁用的不好,就会陷入死锁,我们以前可以使用Object的wait/notify来解决死锁问题.也可以使用Condition的awai ...
- JVM 源码分析(四):深入理解 park / unpark
前言 Parker 源码调试与分析 park/unpark 原理总结 补充:jstack 命令和 kill 命令 前言 熟悉 Java 并发包的人一定对 LockSupport 的 park/unpa ...
- jdk提供的线程协调API suspend/resume wait/notify park/unpark
线程通信(如 线程执行先后顺序,获取某个线程执行的结果等)有多种方式: 文件共享 线程1 --写入--> 文件 < --读取-- 线程2 网络共享 变量共享 线程1 --写入--> ...
- java 之 wait, notify, park, unpark , synchronized, Condition
1. wait notify /** * 解释: 唤醒一个等待monitor的线程, 如果有多个线程在等待,会唤醒一个. * 一个线程在等待monitor是由Object.wait引起的 * 获取一个 ...
- LockSupport中的park()与unpark()
类注释原文:Basic thread blocking primitives for creating locks and other synchronization classes.意思就是Lock ...
- java park unpark
https://blogs.oracle.com/dave/a-race-in-locksupport-park-arising-from-weak-memory-models https://blo ...
- Java的LockSupport.park()实现分析
LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了主要的线程同步原语.LockSupport实际上是调用了Unsafe类里的函数,归结到Unsafe里,仅仅有两个函数: ...
- 4.锁定--Java的LockSupport.park()实现分析
LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了主要的线程同步原语. LockSupport实际上是调用了Unsafe类里的函数.归结到Unsafe里,仅仅有两个函数: ...
随机推荐
- ReSharper插件功能介绍
ReSharper是一款功能非常强悍的Visual Studio的辅助插件,这款插件可用于C#,VB.net,XML,Asp.net,XAML,和构建脚本.ReSharper 9.1版本大改进对 Ja ...
- NGUI之Toggle实现单选框
一:使用步骤——创建一个checkboxes 1.首先在UI Root下建立一个Sprite,设置一张贴图,当作按钮的背景. 然后为其添加碰撞组件和Toggle组件 2.为第一个Sprite建立一个子 ...
- linux环境中,查询网卡的速度(带宽)
需求描述: 今天一同事要整理测试环境的主机硬件配置信息,需要提供网卡的速度的信息, 所以,就查询了下,在此记录下. 操作过程: 1.首先通过ip a命令查询主机的网口名称 [root@redhat6 ...
- Java精选笔记_Java入门
Java概述 什么是Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言 JavaSE标准版 是为开发普通桌面和商务应用程序提供的解决方案 JavaEE企业版 是为开发企业级应用程序提供的解 ...
- 如何连接 MySQL
操作如下: [root@localhost ~]$ mysql -uroot -p' # 本地连接 MySQL 服务 [root@localhost ~]$ mysql -uroot -p' -h19 ...
- thinkjs——moment.js之前后台引入问题
前言: 工作中时常会遇见处理时间格式化问题:简言之就是将存在数据库中的时间戳的数字以“YYYY-MM-DD HH:mm:ss”格式展现出来. 过程: 1.在html文件中,通常是引入moment.js ...
- SDWebImage使用,图片加载和缓存
本文转载至 http://blog.163.com/wzi_xiang/blog/static/659829612012111402812726/ 清除缓存: [[SDImageCache s ...
- 计算时间:一个C++运算符重载示例
Time类是一个用于计算时间的类,其原型如下:程序清单11.1 mytime0.h // mytime0.h -- Time class before operator overloading #if ...
- 判断页面中的js方法是否存在,存在就调用它,不存在则忽略
if(typeof queryResource != 'undefined' && queryResource instanceof Function) queryResource(a ...
- Vscode 修改为中文语言
1 官网下载最新版的vscode : https://code.visualstudio.com/Download 2 安装之后, 按键 F1 搜索框 输入 language 选择 config ...