Java Concurrent之LockSupport

LockSupport为Java锁和同步类提供了基础的线程阻塞原语。
LockSupport可以通过park或者unpark方法来阻塞和唤醒线程,通过unpark/park方法来阻塞唤醒线程不会出现Thread.suspend/Thread.resume引起的死锁问题。
LockSupport和每一个使用它的线程都会与一个许可关联,而且许可只能有一个,不可累积。如果许可可用的话,并且可以在进程使用的话,调用park就立即返回,否则如果许可已经被占用的话,当前线程就会阻塞,直到调用unpark方法,获取许可。
由于许可是默认被占用的,当你调用park的话就获取不到许可,所以就进入阻塞状态。
而且LockSupport是不可重入的,当你一次线程执行两次LockSupport.park的话,线程就会一直阻塞下去。

源码分析

成员变量

sun.misc.Unsafe可以直接操作内存,可以用来做性能监控和开发工具。
parkBlockerOffset是指parkBlocker的偏移量,parkBlocker主要用来记录线程被阻塞的时候是被谁阻塞的,可以通过getBlocker获取阻塞的对象。在静态初始化的时候,通过反射获取Thread类parkBlocker字段对象,然后调用unsafe获取字段对象在内存中偏移量,由于parkBlocker是在线程阻塞的时候在会被设置的,直接调用线程内的方法是不会被调用的,只能通过操作内存的方式才能设置。

1
2
3
4
5
private static final sun.misc.Unsafe UNSAFE;
private static final long parkBlockerOffset;
private static final long SEED;
private static final long PROBE;
private static final long SECONDARY;

静态初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static {
try {
UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> tk = Thread.class;
parkBlockerOffset = UNSAFE.objectFieldOffset
(tk.getDeclaredField("parkBlocker"));
SEED = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSeed"));
PROBE = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomProbe"));
SECONDARY = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSecondarySeed"));
} catch (Exception ex) { throw new Error(ex); }
}

主要方法

  • park
    为了线程调度,在许可可用之前阻塞当前线程。如果许可可用,则使用该许可,并且该调用立即返回;否则的话就会阻塞当前线程,除非其他线程调用将当前线程作为目标调用unpark、或者其他线程中断当前线程、或者该调用不合逻辑地返回。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
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);
}
}
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 parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
public static void parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
  • unPark
    如果给定线程的许可尚不可用,则使其可用。如果线程在park上阻塞,则它将解除其阻塞状态。否则,保证下一次调用park 不会受阻塞。如果给定线程尚未启动,则无法保证此操作有任何效果。
1
2
3
4
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
  • getBlocker
    从给定线程中获取对应的parkBlocker对象,返回的是阻塞线程的Blocker对象。
1
2
3
4
5
public static Object getBlocker(Thread t) {
if (t == null)
throw new NullPointerException();
return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
}
  • setBlocker
    对跟定线程的parkBlocker进行设置,是一个私有方法,不允许被其他地方进行调用,防止误用。
1
2
3
private static void setBlocker(Thread t, Object arg) {
UNSAFE.putObject(t, parkBlockerOffset, arg);
}

COMMENT AND SHARE

冼毅俊

Xupter√Java√德桌迷√虐心控√mugen爱好者√音乐杂食党√小说发烧友√基本色√鱼迷√stan√bitch√daydreamer


Java研发


长安