首页 > 其他 > 详细

wait/notify对比park/unpark

时间:2021-05-05 17:43:51      阅读:38      评论:0      收藏:0      [点我收藏+]

一、原理:

1、当thread0获得ojb的Monitor锁时,发现不满足条件,进入WaitSet变为WAITTING状态;

2、BLOCKED和WAITING状态的线程都是阻塞状态,不占用cpu;两者是由区别的,WAITING是已经获得过锁,但是又放弃了锁;BLOCKED是正在等待去获取锁;

3、owner线程释放锁时,会唤醒EntryList中的BLOCKED状态的线程;ower线程调用notify或notifyAll方法时会唤醒WaitSet中的线程,让其进入READY就绪状态;

技术分享图片

 

 二、使用

技术分享图片技术分享图片

obj.wait();让进入object监视器的线程进入WaitSet等待;

obj.notify();从object监视器的WaitSet中挑一个线程唤醒,让其进入就绪状态;

obj.notifyAll();将object监视器的WaitSet中全部线程唤醒

他们都是线程之间进行协调的手段,都是属于Object对象的方法,所以必须先获得obj的锁,才能调用obj的这几个方法。

sleep和wait的区别

sleep是Thread的静态方法,wait是Object类的实例方法;

sleep不需要和synchronized配合使用,wait需要;

sleep不会释放对象的锁,wait会释放锁;

公共点:调用两种方法之后,线程都是进入timed_waiting状态。

实战:

技术分享图片技术分享图片技术分享图片

 notify只能唤醒某一个不确定的线程,所以可能造成虚假唤醒(小南线程被唤醒,但是条件依然不满足),所以需要使用notifyAll方法全部唤醒。

 同步模式保护性暂停:一个线程等待另一个线程的执行结果。

import java.util.concurrent.TimeUnit;
public class Test01 {
public static void main(String[] args) {
MyGuardedObject myGuardedObject = new MyGuardedObject();
new Thread(() -> {
System.out.println("等待t2的执行结果");
Object result = myGuardedObject.get();
System.out.println("等待的结果:" + result);
}, "t1").start();

new Thread(() -> {
System.out.println("执行线程t2.。。。");
String result = "t1需要的结果";
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
}
myGuardedObject.complete(result);
}, "t2").start();
}
}

class MyGuardedObject{
private Object response;

public Object get() {
synchronized (this) {
while (response == null) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
}
}
return response;
}
}
public void complete(Object response) {
synchronized (this) {
this.response = response;
this.notifyAll();
}
}
}

对比join的方式,这种通过共同关联一个第三方对象的方式更加灵活。

park和unpark

park和unpark方法是LockSupport的静态方法,作用是暂停线程,线程进入waiting状态,unpark唤醒线程,使线程从waiting进入就绪状态。

park方法可以在unpark之后调用,也就是先unpark了,后面再执行park时,unpark的唤醒效果还可以起作用:

技术分享图片

 

原理解析:每个线程都有一个自己的Parker对象,其中有一个counter属性,默认值为0,线程调用park方法时,检查counter是否为0,是的话进入等待状态,调用unpark方法则线程会将counter变量值设为1(扩展一点,unpark可以多次调用,效果只是将counter设为1),同时唤醒等待的线程。如果线程正在运行,先调用unpark方法,counter值变为1,线程不受影响,继续运行,然后调用park方法,这时线程会检查counter的值,发现counter=1,这时的操作是将counter置为0,然后继续运行。

 对比wait、notify,park、unpark不用配合synchronized锁来使用,所以更加灵活;

unpark可以精确唤醒某一个线程,notify不能;

 

wait/notify对比park/unpark

原文:https://www.cnblogs.com/dust-to-dust/p/14687817.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!