LockSupport
LockSupport类是基本的线程阻塞组件,在锁和其他同步器中都会使用到。park和unpark是它最核心的两个方法。
LockSupport替代了Thread.suspend和Thread.resume的功能,Thread的suspend和resume方法已经在JDK2中被弃用,原因是suspend方法在挂起线程时,并不会释放该线程持有的锁,这样可能会导致死锁。
1 | //LockSupport.java |
如果已经存在一个许可的话(这里的许可可以通过调用unpark获取),调用park会立即返回。
如果没有许可的话,调用park会阻塞,需等待其他地方调用unpark唤醒。
许可不能累加,也就是说如果多次调用unpark,许可还是只有一个,只能允许后面一个park调用立即返回,第二个park会阻塞。
park方法应该放在一个循环中使用,因为会存在虚假唤醒的情况。
在LockSupport的实现中,UNSAFE.park()和UNSAFE.unpark()是native方法。在openjdk/hotspot/src/share/vm/prims/unsafe.cpp可以找到UNSAFE的实现(thread->parker()->park(isAbsolute != 0, time);
)UNSAFE调用了Parker类的方法。以下为linux下park、unpark的实现。有关许可的部分,是借助了_counter变量来实现的。
该实现主要使用了Pthread中的互斥锁和条件变量。有关Pthread可参考。
1 | //openjdk/hotspot/src/os/linux/vm/os_linux.cpp |
1 | class Parker : public os::PlatformParker { |
每个Java线程持有一个Parker实例,每个Parker实例中持有一个条件变量和互斥锁,因此当调用unpark唤醒的时候,是可以指定唤醒哪个线程的。