Java并发编程(七) wait notify

1、Monitor

Monitor 被翻译为 监视器 管程
每个 Java 对象都可以关联一个 Monitor 对象,如果使用 synchronized 给对象上锁(重量级)之后,该对象头的Mark Word 中就被设置指向 Monitor 对象的指针
 
Monitor 结构如下
  • 刚开始 Monitor Owner null
  • Thread-2 执行 synchronized(obj) 就会将 Monitor 的所有者 Owner 置为 Thread-2Monitor中只能有一个Owner
  • Thread-2 上锁的过程中,如果 Thread-3Thread-4Thread-5 也来执行 synchronized(obj),就会进入EntryList BLOCKED
  • Thread-2 执行完同步代码块的内容,然后唤醒 EntryList 中等待的线程来竞争锁,竞争的时是非公平的
  • 图中 WaitSet 中的 Thread-0Thread-1 是之前获得过锁,但条件不满足进入 WAITING状态的线程
synchronized 必须是进入同一个对象的 monitor 才有上述的效果
不加 synchronized 的对象不会关联监视器,不遵从以上规则
 

2、wait notify

API 介绍
  • obj.wait() 让进入 object 监视器的线程到 waitSet 等待
  • obj.notify() object 上正在 waitSet 等待的线程中挑一个唤醒
  • obj.notifyAll() object 上正在 waitSet 等待的线程全部唤醒

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

public class Demo {
	final static Object obj = new Object();

	public static void main(String[] args) {
		new Thread(() -> {
			synchronized (obj) {
				log.debug("执行....");
				try {
					obj.wait(); // 让线程在obj上一直等待下去
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				log.debug("其它代码....");
			}
		}).start();
		new Thread(() -> {
			synchronized (obj) {
				log.debug("执行....");
				try {
					obj.wait(); // 让线程在obj上一直等待下去
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				log.debug("其它代码....");
			}
		}).start();
		// 主线程两秒后执行
		sleep(2);
		log.debug("唤醒 obj 上其它线程");
		synchronized (obj) {
			obj.notify(); // 唤醒obj上一个线程
			// obj.notifyAll(); // 唤醒obj上所有等待线程
		}
	}
}
notify 的一种结果
20:00:53.096 [Thread-0] c.TestWaitNotify - 执行.... 
20:00:53.099 [Thread-1] c.TestWaitNotify - 执行.... 
20:00:55.096 [main] c.TestWaitNotify - 唤醒 obj 上其它线程
20:00:55.096 [Thread-0] c.TestWaitNotify - 其它代码....
notifyAll 的结果
19:58:15.457 [Thread-0] c.TestWaitNotify - 执行.... 
19:58:15.460 [Thread-1] c.TestWaitNotify - 执行.... 
19:58:17.456 [main] c.TestWaitNotify - 唤醒 obj 上其它线程
19:58:17.456 [Thread-1] c.TestWaitNotify - 其它代码.... 
19:58:17.456 [Thread-0] c.TestWaitNotify - 其它代码....
  • wait() 方法会释放对象的锁,进入 WaitSet 等待区,从而让其他线程就机会获取对象的锁。无限制等待,直到notify 为止
  • wait(long n) 有时限的等待, n 毫秒后结束等待,或是被 notify

wait notify 的正确姿势

sleep(long n) wait(long n) 的区别
 
1) sleep Thread 方法,而 wait Object 的方法
2) sleep 不需要强制和 synchronized 配合使用,但 wait 需要和 synchronized 一起用
3) sleep 在睡眠的同时,不会释放对象锁的,但 wait 在等待的时候会释放对象锁
4) 它们状态 TIMED_WAITING
 
synchronized(lock) {
 while(条件不成立) {
 lock.wait();
 }
 // 干活
}
//另一个线程
synchronized(lock) {
 lock.notifyAll();
}
模式之保护性暂停
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值