JUC并发编程——wait / notify原理

Monitor 中有三个部分:Owner,EntrySet 和 WaitSet。
在这里插入图片描述

Owner 是拥有锁的线程地址,EntrySet 是其他线程想要获取锁的列表,WaitSet 是拥有锁的线程一些条件未满足调用 wait() 方法,进入的WaitSet列表,并且释放锁。

在 EntryList 中的线程状态是 BLOCKED,在 WaitSet 中的线程状态是 WAITING。都不占用 CPU 时间片。

wait()执行过程

拥有锁的线程t0调用 wait() 方法,t0进入 WaitSet 列表,且释放锁,同时 EntryList 中的线程得到锁,得到锁的线程t1可以通过 notify() 随机唤醒一个在 WaitSet 里的线程,也可使用 notifyAll()方法唤醒所有线程。被唤醒的线程先执行完wait() 后的代码,再进入 EntryList 列表,等待锁的释放。

关于 wait()的API

  • wait(0):释放锁,一直等待,直到被唤醒。

    wait(0) 默认就是一直等待

  • wait(long n):有时限的等待,到 n 毫秒后结束等待,或是被 notify()

sleep(long n) 和 wait(long n) 的区别

1)sleep 是 Thread 方法,wait 是 Object 方法(所有类的对象都可以调用)
2)sleep 不需要配合 synchronized 使用,但 wait 需要和 synchronized 一起用
3)sleep 在睡眠的同时,不会释放对象锁的,但 wait 在等待的时候会释放对象锁
4)它们的状态都是 TIMED_WAITING(wait() =》WAITING)

wait() 和 notify() 的正确使用姿势:

synchronized(lock) {
	while(条件不成立) {
		lock.wait();
	}
	// 干活
}

//另一个线程
synchronized(lock) {
	lock.notifyAll();
}

其他API

park 和 unpark

它们是 java.util.concurrent 包下 LockSupport 类中的方法。

// 暂停当前线程
LockSupport.park(); 

// 恢复某个线程的运行
LockSupport.unpark(暂停线程对象)

与Object 的 wait & notify 相比

  • wait,notify 和 notifyAll 必须配合 Object Monitor 一起使用,而 park,unpark 不必
  • park & unpark 是以线程为单位来【阻塞】和【唤醒】线程,而 notify 只能随机唤醒一个等待线程,notifyAll 是唤醒所有等待线程,就不那么【精确】
  • park & unpark 可以先 unpark,而 wait & notify 不能先 notify
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值