JAVA多线程学习系列 - 等待wait/通知notify

/**
 * 线程之间的等待/通知机制
 * 
 * @author Shawn Wong
 *
 */
public class WaitNotifyThread {

	private static Object lock = new Object();

	private static volatile boolean flag = true;

	public static void main(String[] args) {

		System.out.println(Thread.currentThread().getName());
		// 等待线程A
		Thread a = new Thread(new WaitThread(), "thread-A");
		a.start();
		// 等待线程B
		Thread b = new Thread(new WaitThread(), "thread-B");
		b.start();
		// 通知线程C
		Thread c = new Thread(new NofifyThread(), "thread-C");
		c.start();
	}

	static class WaitThread extends Thread {

		@Override
		public void run() {
			test();
		}

		void test() {
			synchronized (lock) {
				while (flag) {
					System.out.println(Thread.currentThread().getName() + " enter loop");
					try {
						lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + " notify");
				}
			}

		}
	}

	static class NofifyThread extends Thread {
		@Override
		public void run() {
			test();
		}

		void test() {
			synchronized (lock) {
				System.out.println("start to notify all wait ");
				lock.notifyAll();
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				flag = false;
				System.out.println("enter ");
			}

		}
	}

}

运行结果:



流程图:


1、 在对象Lock上添加Synchronized关键字,锁会被记录在Lock的对象头中,并在被锁的程序块的前后分别添加了monitor.enter 和monitor.exit的字节码, 程序走到monitor.exit后会立即释放锁,其他线程才能再次获取到锁,从而进入到代码块中,保证了顺序性(一致性)和可见性。

2、如果线程A在monitor.enter成功后,但没有走完monitor.exit的字节码,线程B此时访问被锁的代码块,monitor.enter会失败,线程B的状态会自动变成BLOCKED,进入阻塞队列中。一旦线程A走完monitor.exit的字节码,线程B会有可能获取到锁,进入代码块。

3、线程A在进入wait()方法时,会自动进入等待队列中,并且释放掉锁,等待其他线程的通知。 由于已经释放了锁,通知线程C就可以获取到锁,并执行对象的notify方法,唤醒进入等待队列中的线程A,只有线程C完全释放掉锁后,等待队列中的线程才会迁移到同步阻塞队列中,即线程C的状态从WAITING变成BLOCKED,再去获取锁。



参考书籍: 《Java并发编程的艺术》


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值