写在前面,JUC基础知识,详见 JUC并发包核心之AbstractQueuedSynchronizer
java并发编程面试必备,详见
- java并发编程面试必备
概述
1、java并发编程JUC并发包系列,LockSupport是最特殊的,底层和AQS无关,反而AQS源码中队列的阻塞和通知,是使用LockSupport来实现的
2、LockSupport不会释放锁,LockSupport不会释放锁,LockSupport不会释放锁。重要的事情说三遍。参见:面试 LockSupport.park()会释放锁资源吗?
源码分析
LockSupport定义了一组以park开头的方法来阻塞当前线程,unpark来唤醒被阻塞的线程。
park方法
public static void park() {
//调用native方法阻塞当前线程。
UNSAFE.park(false, 0L);
}
//阻塞当前线程,最长不超过nanos纳秒,返回条件在park()的基础上增加了超时返回。
public static void parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
//阻塞当前线程,直到deadline(deadline - 毫秒数)。
public static void parkUntil(long deadline) {
UNSAFE.park(true, deadline);
}
unPark方法
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
使用方法
1、线程1加到10,线程2,如果加到5,输出一下提示就结束
public class TestLockSupport {
//容器,提供add size方法
//线程1加到10,线程2,如果加到5,输出一下提示就结束
private List<Object> list = new ArrayList<>();
public void add(Object o) {
list.add(o);
}
public int size() {
return list.size();
}
static Thread t1 = null, t2 = null;
public static void main(String[] args) {
TestLockSupport testLockSupport = new TestLockSupport();
t1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
testLockSupport.add(new Object());
System.out.println("add " + i);
if (testLockSupport.size() == 5) {
LockSupport.unpark(t2);
LockSupport.park();
}
}
}, "t1");
t2 = new Thread(() -> {
LockSupport.park();
System.out.println("t2 end");
LockSupport.unpark(t1);
}, "t1");
t2.start();
t1.start();
}
}
执行结果:
add 0
add 1
add 2
add 3
add 4
t2 end
add 5
add 6
add 7
add 8
add 9
2、交替输出A1B2C3…同样的题目参见ReentranLock的实现:java并发编程JUC并发包之ReentrantLock
public class Test_A1B2C3_LockSupport {
private static Thread t1 = null, t2 = null;
public static void main(String[] args) {
t1 = new Thread(() -> {
for (int i = 0; i < 3; i++) {
LockSupport.park();
System.out.print((char)(65 + i));
LockSupport.unpark(t2);
}
});
t2 = new Thread(() -> {
for (int i = 0; i < 3; i++) {
LockSupport.unpark(t1);
LockSupport.park();
System.out.print(i);
}
});
t2.start();
t1.start();
}
}
执行结果:
A0B1C2