1 LockSupport 概述
LockSupprot是线程的阻塞原语,用来阻塞线程和唤醒线程。每个使用LockSupport的线程都会与一个许可关联,如果该许可可用,并且可在线程中使用,则调用park()将会立即返回,否则可能阻塞。如果许可尚不可用,则可以调用 unpark 使其可用。但是注意许可不可重入,也就是说只能调用一次park()方法,否则会一直阻塞。
2 LockSupport API
获取许可相关
//获取许可,如果成功则直接返回,失败则一直阻塞当前线程。
//直到系统调用unpark方法或者当前线程被中断时可以从阻塞中唤醒从park()方法中返回
public static void park() {
UNSAFE.park(false, 0L);
}
//功能同park()方法,增加了一个Object对象参数,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
//功能同park()方法,增加了一个超时时间nanos(纳秒),如果线程获取许可失败,阻塞不再是永久,而时增加了超时返回的特性;
public static void parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
//功能同parkNanos,增加了一个Object对象参数,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;
public static void parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
//功能同park()方法,这里超时时间变成了绝对的超时时间,超时时间单位变成纳秒。
public static void parkUntil(long deadline) {
UNSAFE.park(true, deadline);
}
//功能同parkUntil,增加了一个Object对象参数,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;
public static void parkUntil(Object blocker, long deadline) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(true, deadline);
setBlocker(t, null);
}
释放许可
//释放一个线程的许可。如果线程在等待许可阻塞,会被唤醒。
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
线程dump
UNSAFE
LockSupport 实现上通过UNSAFE实现。特性上和UNSAFE相同,我们来回顾下UNSAFE 特性:
-
默认情况下线程中不存在许可。当前线程第一次使用Unsafe 调用park方法时(如果未调用unpark)会导致当前线程阻塞。
-
同一个线程多次归还许可只和一次归还相同
-
unpark 无法恢复处于 sleep 中的线程,只能与 park 配对使用,因为 unpark 发放的许可只有 park 能监听到。
使用例子
package locksupport;
import org.junit.Test;
import java.util.concurrent.locks.LockSupport;
public class LockSupportTest {
@Test
public void park1(){
LockSupport.park();
}
@Test
public void park2(){
long star=System.currentTimeMillis();
LockSupport.parkNanos(5000000000L);
System.out.println(System.currentTimeMillis()-star);
}
@Test
public void park3(){
long star=System.currentTimeMillis();
LockSupport.parkUntil(System.currentTimeMillis()+5000L);
System.out.println(System.currentTimeMillis()-star);
}
@Test
public void park5() {
Thread currThread = Thread.currentThread();
LockSupport.unpark(currThread);
LockSupport.unpark(currThread);
LockSupport.unpark(currThread);
LockSupport.park();
LockSupport.park();
System.out.println("execute success"); // 线程挂起,不会打印。
}
}
网友评论