Java多线程【2】Java wait/notify的使用于同步模式保护性暂停

系列文章目录


Java多线程【1】synchronized对象锁、内置锁使用
Java多线程【2】Java wait/notify的使用于同步模式保护性暂停
Java多线程【3】同步模式之保护性暂停案例 相亲问题
Java多线程【4】interrupt线程的打断机制、两阶段终止模式
Java多线程【5】异步模式之生产者消费者
Java多线程【6】LockSupport park/unpark原理和使用以及于wait/notify的区别


前言

当线程调用sleep()、join()方法的时候,线程会进入WAIT状态,按照操作系统的视角线程处于BLOCK状态。线程获取轻量级锁失败时进入锁膨胀,会为锁对象申请一个monitor对象(监视器、管程),monitor对象中有两个队列,EntryList(同步队列)、WaitSet(等待队列)。wait方法会使当前线程进入到WaitSet队列。


一、wait、notify、notifyAll

1.1、同步阻塞的区别和wait方法的区别

  • 线程获取锁失败,线程会进入monitor对象的EntryList队列中等待,直到锁被释放,EntryList中的线程会不公平的被CPU调度。
  • 当线程获取锁之后,调用锁对象的wait方法,这时候会立马释放锁。当前线程不会进入EntryList,而是进入WaitSet等待队列。
    示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

1.2、notify方法

  • 当前调用锁对象的notify时,会将锁对象的WaitSet队列中的线程随机拿出一个,移动到EntryList队列中
  • 等待线程释放锁,EntryList里面的线程不公平的被CPU调度。

1.3、notifyAll方法

  • 当前调用锁对象的notifyAll时,会将锁对象的WaitSet队列中的线程全部拿出,移动到EntryList队列中
  • 等待线程释放锁,EntryList里面的线程不公平的被CPU调度。

二、同步模式之保护性暂停

2.1、保护性暂停和轮询等待(cas)的区别

保护性暂停可以理解为一个线程等待另一个线程的结果返回后开始执行操作。例如我要泡茶的前提是我需要去买茶叶,那么买茶叶线程执行完成,我买到了茶叶才能开始泡茶线程。类似用volatile的元素在线程做轮询判断也可实现效果

  • 轮询等待的过程中会一直占用CPU时间片,导致资源浪费。
  • 保护性暂停会让线程进入BLOCK状态(java中的WAITING或者TIMED_WAITING),从而让出CPU资源。

2.2、Guarded Suspension

有一个结果需要从一个线程传递到另外一个线程,让两个线程关联同一个GuardedObject。

  		GuardedObject guardedObject = new GuardedObject();
        new Thread(new Runnable() {
            @Override
            public void run() {
                Object o = guardedObject.get();
                System.out.println(o);
            }
        },"线程1").start();



        new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                TimeUnit.SECONDS.sleep(2);
                guardedObject.set("123123123");
            }
        },"线程2").start();
        
        TimeUnit.SECONDS.sleep(10);
    }

2.3、Guarded Suspension Time Out

	
@Slf4j
public class GuardedObject {

    private Object response;


    public Object getResponse() {
        return response;
    }

    public void setResponse(Object response) {
        this.response = response;
    }

    public Object get(Integer timout){
        long startTime = System.currentTimeMillis();
        long expenseTime = 0;
        long waitTime = timout - expenseTime;
        while (response == null){
            if(expenseTime < waitTime){
                synchronized (this){
                log.info("等待线程返回数据...");
                    try {
                        this.wait(waitTime);
                        expenseTime =  System.currentTimeMillis() -startTime ;
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }else {
                break;
            }
        }
        log.info("线程返回数据...");
        log.info("经历时间..."+expenseTime);

        return this.getResponse();
    }


    public void set(Object data){
        this.setResponse(data);
        synchronized (this){
            this.notify();
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王乐乐君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值