一、LockSupport
1、是什么
LockSupport是线程阻塞和唤醒的工具类。
LockSupport是通过park()和unpark()实现线程等待唤醒。
LockSupport类使用了Permit(许可)的概念来阻塞和唤醒线程的。每个线程都有一个许可。
2、源码
public static void park() {
UNSAFE.park(false, 0L);
}
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
底层通过调用unsafe调用外部 C++,采用 CAS 算法。
二、JUC 之 3 中线程阻塞和唤醒
方式一:synchronized
wait和notify方法,必须要在同步块或者方法里面,且成对出现使用,先wait后notify。
方式二:lock
Condition中的线程等待和唤醒方法,需要先获取锁,且先await后signal。
方式三:LockSupport
无锁块要求,因为它本身带锁;
唤醒和阻塞没有顺序,LockSupport一样支持,因为它是通过许可来进行阻塞和唤醒的。
调用park()时:无许可,进行线程阻塞;
调用unpark()时:有许可,唤醒被阻塞的线程。
针对上面 3 种线程的阻塞和唤醒的方式提供一下代码案例:
/**
* @descpription: 线程的阻塞和唤醒
* @date 2024/6/12
*/
public class LockSupportDemo {
public static void main(String[] args) {
// waitAndNotifyAll();
// awaitAndSignalAll();
parkAndUnPark();
}
private static void awaitAndSignalAll() {
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
new Thread(() -> {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + "\t come in");
try {condition.await();} catch (InterruptedException e) {throw new RuntimeException(e);}
try {TimeUnit.MILLISECONDS.sleep(400);} catch (InterruptedException e) {throw new RuntimeException(e);}
System.out.println(Thread.currentThread().getName() + "\t t1 被唤醒");
} finally {
lock.unlock();
}
}, "t1").start();
try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {throw new RuntimeException(e);}
new Thread(() -> {
try {
lock.lock();
condition.signalAll();
System.out.println(Thread.currentThread().getName() + "\t t2 唤醒t1");
} finally {
lock.unlock();
}
}, "t2").start();
}
private static void waitAndNotifyAll() {
final Object obj = new Object();
new Thread(() -> {
synchronized (obj) {
System.out.println(Thread.currentThread().getName() + "\t come in");
try {obj.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}
try {TimeUnit.MILLISECONDS.sleep(400);} catch (InterruptedException e) {throw new RuntimeException(e);}
System.out.println(Thread.currentThread().getName() + "\t t1 被唤醒");
}
}, "t1").start();
try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {throw new RuntimeException(e);}
new Thread(() -> {
synchronized (obj){
obj.notifyAll();
System.out.println(Thread.currentThread().getName() + "\t t2 唤醒t1");
}
}, "t2").start();
}
private static void parkAndUnPark() {
Thread t1 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t come in");
LockSupport.park();
System.out.println(Thread.currentThread().getName() + "\t t1 被唤醒");
}, "t1");
t1.start();
try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {throw new RuntimeException(e);}
new Thread(() -> {
LockSupport.unpark(t1);
System.out.println(Thread.currentThread().getName() + "\t t2 唤醒t1");
}, "t2").start();
}
}