zoukankan      html  css  js  c++  java
  • 《Java并发编程的艺术》读书笔记:等待/通知机制

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

        线程调用wait()后,会释放已经获得的锁。

    同一时候进入Waiting状态,而非Blocked状态。唯独等待其它的线程调用notify()方法且释放锁之后。当前线程才会从wait()方法处返回。只发出通知是不够用的。还须要发出通知的线程释放锁。

    然而notify()方法的调用并不意味着锁的释放。

        贴出原书的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。

  • 相关阅读:
    第194场周赛
    刷leetcode的心得
    91. Decode Ways
    23. Merge k Sorted Lists
    19. Remove Nth Node From End of List
    21. Merge Two Sorted Lists
    222. Count Complete Tree Nodes
    958. Check Completeness of a Binary Tree
    课程学习总结报告
    结合中断上下文切换和进程上下文切换分析Linux内核一般执行过程
  • 原文地址:https://www.cnblogs.com/mthoutai/p/7290146.html
Copyright © 2011-2022 走看看