LockSupport使用,以及与wait/notify await/signal的比较
作者:互联网
LockSupport通过pack 和 unpark 的方法来实现阻塞和唤醒线程的操作
Locksupport l类使用了一种名为permit 许可证的概念来做到阻塞和唤醒线程的功能,每个线程都有一个许可证permit,Permit只有两个值 1 和0 默认是0
使用Locksupport 的pack 和unpark方法 实现wait/notify await/signal的阻塞 唤醒功能
1.使用wait/notify阻塞唤醒
package com.example.starter;
public class LockSupportDemo {
static Object objectLock = new Object();
public static void main(String[] args) {
new Thread(()->{
synchronized (objectLock){
System.out.println(Thread.currentThread().getName()+" come in ");
try {
objectLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 被唤醒");
}
},"AA").start();
new Thread(()->{
synchronized (objectLock){
objectLock.notify();
System.out.println(Thread.currentThread().getName()+" 通知");
}
},"BB").start();
}
}
结果
AA come in
BB 通知
AA 被唤醒
不足:必须绑定synchronize使用,如果线程BB先运行,那么线程AA将永远不会被唤醒
2.使用await/signal的方式实现阻塞唤醒
public class LockSupportDemo {
static Object objectLock = new Object();
static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args) {
new Thread(() ->{
/*try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+" come in ");
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
System.out.println(Thread.currentThread().getName()+" 被唤醒");
},"AA").start();
new Thread(()->{
lock.lock();
try {
condition.signal();
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
System.out.println(Thread.currentThread().getName()+" 通知");
},"BB").start();
}
结果
AA come in
BB 通知
AA 被唤醒
不足:必须绑定Lock使用,如果线程BB先运行,那么线程AA将永远不会被唤醒
3.使用lockSupport 的park 和unpark的方式
public class LockSupportDemo {
static Object objectLock = new Object();
static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" come in ");
LockSupport.park();
System.out.println(Thread.currentThread().getName()+" 被唤醒");
}, "AA");
threadA.start();
new Thread(() -> {
LockSupport.unpark(threadA);
System.out.println(Thread.currentThread().getName()+" 通知了");
}, "BB").start();
}
结果
AA come in
BB 通知
AA 被唤醒
优点:不在依赖任何其他组件,BB线程先运行 AA也能正常唤醒
注意调用两次unpark 和 park 无论调用多少次unpark都只会发放一次通行证,而调用几次park就会要几张通行证,如下代码所示,会导致AA无法唤醒
public class LockSupportDemo {
static Object objectLock = new Object();
static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
System.out.println(Thread.currentThread().getName()+" come in ");
LockSupport.park();
LockSupport.park();
System.out.println(Thread.currentThread().getName()+" 被唤醒");
}, "AA");
threadA.start();
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
LockSupport.unpark(threadA);
LockSupport.unpark(threadA);
System.out.println(Thread.currentThread().getName()+" 通知了");
}, "BB").start();
}
结果
AA come in
BB 通知了
关注下park和unpark的底层实现:
都是调用的底层unsafe类
标签:AA,Thread,signal,await,LockSupport,static,println,new,唤醒 来源: https://blog.csdn.net/ym563099457/article/details/121323300