深入java虚拟机:原子操作ParkEvent和Parker

本文深入探讨了Java虚拟机中的原子操作、ParkEvent和Parker,详细阐述了它们在HotSpot VM并发基础设施中的作用。原子操作利用CPU指令实现不可打断的操作,而ParkEvent和Parker则是线程睡眠与唤醒的关键。Parker可以视为受限的信号量,常用于JSR166并发组件。Monitor作为HotSpot VM内部并发的核心,采用了fast/slow路径设计,保证了性能和扩展性的平衡。
摘要由CSDN通过智能技术生成

基础设施

HotSpot VM并发的基础设施主要是原子操作、ParkEvent和Parker,后面两个功能的重合度很高,未来可能合并为一个ParkEvent。在笔者写这本书的时候(jdk-12+31),它们两个还是独立的个体,所以文中会分别讨论。

 原子操作

原子操作即普通意义上的不可打断的操作。HotSpot VM的原子模块位于runtime/atomic,它实现了原子性的递增值、交换值、比较并交换等操作,其底层实现依赖于CPU指令。举个例子,x86提供lock指令前缀,以保证一个CPU在执行被修饰的指令期间互斥地拥有对应的Cache Line的所有权。这个保证是并发的基础,并发离不开线程,线程离不开锁,如果多个线程在同一时刻抢锁(互斥量/同步量),锁内部就必须有一条只能互斥执行的代码,这便是原子指令。

ParkEvent

使用ParkEvent可以使线程睡眠与唤醒。一个ParkEvent与一个线程的生命周期绑定,当线程结束时,ParkEvent会移到一个EventFreeList链表,而新创建的线程会在EventFreeList中查找ParkEvent,如果没有就分配新的ParkEvent。ParkEvent本身只有分配和释放接口,但是它继承了平台相关的PlaformEvent,因此它就有了PlatformEvent提供的park、unpark接口,如代码清单6-9所示:

代码清单6-9 POSIX PlatformEvent的实现

void os::PlatformEvent::park() {
// CAS递减_event的值
int v;
for (;;) {
v = _event;
if (Atomic::cmpxchg(v - 1, &_event, v) == v) break;
}
if (v == 0) {
int status = pthread_mutex_lock(_mutex);
// 阻塞线程加一
++_nParked;
// 如果递减之后event为-1则阻塞,否则立刻返回
while (_event < 0) {
status = pthread_cond_wait(_cond, _mutex);
}
// 阻塞线程减一
--_nParked;
_event = 0;
status = pthread_mutex_unlock(_mutex);
OrderAccess::fence();
}
}void os::PlatformEvent::unpark() {
// 如果_event大于等于0,则设置为1并返回
if (Atomic::xchg(1, &_event) >= 0) return;
// 仅当_event为-1时,即另一个线程阻塞住时才执行后面的唤醒另一个线程的操作
int status = pthread_mutex_lock(_mutex);
int anyWaiters = _nParked;
status = pthread_mutex_unlock(_mutex);
if (anyWaiters != 0) {
status = pthread_cond_signal(_cond);
}
}

ParkEvent依赖的假设是它只被当前绑定的线程park,但是允许多个线程unpark。了解Windows的读者都知道,Windows内核有可以作为同步工具的Event内核对象。当一个操作完成时,可以将Event对象设置为触发状态,此时等待Event事件的线程将得到通知。ParkEvent在Windows上是通过Event内核对象实现的,由于内核的原生支持,其实现也比POSIX简单不少,如代码清单6-10所示:

代码清单6-10 Windows PlatformEvent的实现

void os::PlatformEvent::park() {
int v;
for (;;) {v = _Event;
if (Atomic::cmpxchg(v-1, &_Event, v) == v) break;
}
if (v != 0) return;
while (_Event < 0) {
DWORD rv = ::WaitForSingleObject(_ParkHandle, INFINITE);
}
_Event = 0;
OrderAccess::fence();
}
void os::PlatformEvent::unpark() {
if (Atomic::xchg(1, &_Event) >= 0) return;
::SetEvent(_ParkHandle);
}

ParkEvent广泛应用于HotSpot VM内部࿰

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值