《Java并发编程的艺术》读书笔记:等待/通知机制

    看这本书之前,对wait和notify认识大概就是,调用wait的线程A阻塞之后,一旦另外有线程调用notify方法,线程A会立刻从wait方法处返回。看完这本书后,发现自己的认识实在太肤浅了。。。。。。

    线程调用wait()后,会释放已经获得的锁。同时进入Waiting状态,而非Blocked状态。只有等待其他的线程调用notify()方法且释放锁之后,当前线程才会从wait()方法处返回。仅仅发出通知是不够用的,还需要发出通知的线程释放锁。然而notify()方法的调用并不意味着锁的释放。锁的释放是在synchronized语句块结束的地方

    贴出原书的demo,稍作了些修改。

 

/**
 *
 */
package chapter04;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 6-11
 */
public class WaitNotify {
	private static final SimpleDateFormat sdf  = new SimpleDateFormat("HH:mm:ss");
	static               boolean          flag = true;
	static               Object           lock = new Object();

	public static void main(String[] args) {
		Thread waitThread = new Thread(new Wait(), "WaitThread");
		waitThread.start();
		sleepSeconds(1);

		Thread notifyThread = new Thread(new Notify(), "NotifyThread");
		notifyThread.start();
	}

	static class Wait implements Runnable {
		public void run() {
			synchronized (lock) {
				// 当条件不满足时,继续wait,同时释放了lock的锁
				while (flag) {
					try {
						System.out.println(CuttentThreadName() + " flag is true. wait @ " + sdf.format(new Date()));
						lock.wait();
						System.out.println(CuttentThreadName() + " gained lock again. wait @ " + sdf.format(new Date()));
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				// 条件满足时,完成工作
				System.out.println(CuttentThreadName() + " flag is false. running @ " + sdf.format(new Date()));
			}
		}
	}

	private static String CuttentThreadName() {
		return Thread.currentThread().getName();
	}

	static class Notify implements Runnable {
		@Override
		public void run() {
			// 加锁,拥有lock的Monitor
			synchronized (lock) {
				// 获取lock的锁,然后进行通知,通知时不会释放lock的锁,
				// 直到当前线程释放了lock后,WaitThread才能从wait方法中返回
				System.out.println(CuttentThreadName() + " hold lock. notify @ " + sdf.format(new Date()));
				lock.notifyAll();
				flag = false;
				sleepSeconds(5);
				System.out.println(CuttentThreadName() + " is releasing lock  @ " + sdf.format(new Date()));
			}
			// 再次加锁
			synchronized (lock) {
				System.out.println(CuttentThreadName() + " hold lock again. sleep @ " + sdf.format(new Date()));
				sleepSeconds(5);
				System.out.println(CuttentThreadName() + " is releasing lock  @ " + sdf.format(new Date()));
			}
		}
	}

	private static void sleepSeconds(int timeout) {
		try {
			TimeUnit.SECONDS.sleep(timeout);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}


     输出结果为:

 

 

WaitThread flag is true. wait @ 20:58:32
NotifyThread hold lock. notify @ 20:58:33
NotifyThread is releasing lock  @ 20:58:38
NotifyThread hold lock again. sleep @ 20:58:38
NotifyThread is releasing lock  @ 20:58:43
WaitThread gained lock again. wait @ 20:58:43
WaitThread flag is false. running @ 20:58:43


    通过输出结果,我们可以发现几个问题。

 

    1.NotifyThread调用notifyAll()方法后,WaitThread并没有立刻从wait()方法处返回。因为这个时候NotifyThread并没有释放锁。

    2.程序61行,NotifyThread第一次释放锁,然而WaitThread不争气,并没有抢到这把锁,依旧处于Blocked状态。

    3.直到67行,NotifyThread再一次释放锁,WaitThread获得了锁,这才从wait()处返回继续执行。

    4.线程从wait()方法返回的前提是,获得synchronized需要的锁。

    分析完原书的demo之后,是否有跟我一样的感觉,曾经的认识是那么的too young too simple。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值