LockSupport使用
一、简介
LockSupport是线程同步工具,定义了一组静态方法控制控制线程的阻塞和同步。
二、分析
2.1 源码
LockSupport源码不长,方法及其用法请看源码注释,源码如下:
package java.util.concurrent.locks;
import sun.misc.Unsafe;
public class LockSupport {
//唤醒指定线程
//如果指定线程阻塞则唤醒
//如果指定线程没阻塞则下次阻塞时直接唤醒
//上述唤醒操作只针对已经启动的线程有效
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
//阻塞当前线程,blocker代表阻塞对象(阻塞线程的同步对象),用于问题排查(使用类型jstack等工具可查看阻塞对象),通常传当前线程this
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
//限时阻塞当前线程,阻塞时间不超过指定纳秒,参数blocker为阻塞对象
public static void parkNanos(Object blocker, long nanos) {
if (nanos > 0) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, nanos);
setBlocker(t, null);
}
}
//限时阻塞当前线程,阻塞时间直到指定时间(绝对时间,自1970年开始的毫秒数)为止,参数blocker为阻塞对象
//the absolute time, in milliseconds from the Epoch
public static void parkUntil(Object blocker, long deadline) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(true, deadline);
setBlocker(t, null);
}
//返回指定线程的阻塞对象,如果线程没阻塞,则返回null
public static Object getBlocker(Thread t) {
if (t == null)
throw new NullPointerException();
return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
}
//阻塞当前线程
public static void park() {
UNSAFE.park(false, 0L);
}
//限时阻塞当前线程,阻塞时间不超过指定纳秒
public static void parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
//限时阻塞当前线程,阻塞时间直到指定时间(绝对时间,自1970年开始的毫秒数)为止
//the absolute time, in milliseconds from the Epoch
public static void parkUntil(long deadline) {
UNSAFE.park(true, deadline);
}
}
2.2 实现
LockSupport核心方法是park和unpark,即是阻塞和唤醒,其实现是采用置标志位,值只有0和1:
- LockSupport.park: 标志位置0;
- LockSupport.unpark: 标志位置1;
注意:
- LockSupport.unpark唤醒操作,同一时刻,多次置标志位,若中间时刻未使用,则标识为仍为1;
- 置标志位只有线程启动后能生效;
三、使用示例
package LockSupportSt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
public class LockSupportPaper {
public static void main(String[] args) throws Exception {
Thread t1 = new TestThread();
t1.start();
TimeUnit.SECONDS.sleep(1);
//唤醒线程
LockSupport.unpark(t1);
System.out.println("unpark t1");
}
static class TestThread extends Thread {
@Override
public void run() {
System.out.println("thread start");
//阻塞,同时指定阻塞对象,即当前线程
LockSupport.park(this);
// LockSupport.parkNanos(1000*1000*1000); //限时阻塞
System.out.println("thread end");
}
}
}
备注:
注释唤醒代码,使用jstack打印阻塞时堆栈的部分片段如下:
"Thread-0" #13 prio=5 os_prio=31 tid=0x00007fd80d833800 nid=0x5803 waiting on condition [0x000070000e756000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076ae33fd8> (a LockSupportSt.LockSupportPaper$TestThread)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at LockSupportSt.LockSupportPaper$TestThread.run(LockSupportPaper.java:21)