synchronized , wait() , notify() and notifyAll()

   !!!!!!!!!!........................................

   这三个东西,很容易,也很容易理解,几句话就轻松搞定了。

   synchronized : 同一时刻只能有一个对象持有锁!

   wait() : 当前线程会进入阻塞状态,并放弃锁

   notify() :则会叫醒某一个线程

   notifyAll():会叫醒所有线程

   可是上面的理解对吗?

   至少最后两个是错的。我原以为自己掌握的还好,可是今天遇到的这些状况却让我

扫描二维码关注公众号,回复: 817140 查看本文章

   不能自信的作出解释。

  

   先看synchronized:

   看下面这个例子,如果直接像下面一样通过一个SynTest对象调用,那么start这个锁就跟没加一样!

   其实这个原因很简单,加锁的对象只能在一处使用,不管你是不是加锁对象本身,t1就是那个加锁的对象,它拥有那个锁,你可以无限的

   调用它的加锁方法。

public class SynTest {	
	public static void main(String[] args) {
		SynTest t1 = new SynTest();
		for(int i = 0 ; i < 10; i++) {
			A a = t1.create();
			t1.start(a);
		}
	}
	
	A create() {
		A a  = new A();
		return a;
	}
	
	class A implements Runnable {
//		SynTest t ;
		@Override
		public void run() {
			 test();
//                       t.test(); (这里test加了synchronized) 
		}
//		A(SynTest t) {
//			this.t = t;
//		}
		
	}	
	 public void test () {
		System.out.println(this);
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public  synchronized void start(Runnable a) {
		new Thread(a).start();
	}
}

    在看wait()和notify() / notifyAll() :

    这两个东西我是误区颇深啊!

    就像下面的代码,我还在一直想着,最后能够把所有的线程都唤醒了..

public class Test {

	public static void main(String[] args) throws InterruptedException {
		init();
		while(!conns.isEmpty()) {
			Conn conn = conns.remove(0);
			conn.start();
			Thread.sleep(100);
		}

	}
	
	static List<Conn> conns = new ArrayList<Conn> ();
	
	static void init() {
		conns.add(new Conn());
		conns.add(new Conn());
		conns.add(new Conn());
	}	
	static class Conn extends Thread {
		
		@Override
		public void run() {
			try {
				send();
				response();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "   get response" );
		}
		
		public synchronized void send() throws InterruptedException {
			if(!conns.isEmpty()) {
				System.out.println(Thread.currentThread().getName() + "   send  A to Server");
				wait();
			} else {
				response();
			}
		}
		
		public synchronized void response() {
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			notifyAll();
		}
	}

}

    首先第一点,这两个东西必须方法在同步代码中,你可以给方法加synchronized 或者给 代码块加!

    

     然后就是notify/notifyAll  , 不是 A.notify() 或者 A.notifyAll() 就会把 B线程唤醒!!!!!

     它是与对象挂钩,那个对象notify就只能notify那些等待这个对象控制权的线程!!!!

     

如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。

   

   关于notify()/notifyAll()还要注意下下面这种情形:

   当调用完了notify() / notifyAll() 的时候,并不等于等待线程就会立马运行,只有等调用完notify()或者notifyAll()

  并退出synchronized块,释放对象锁后,其余线程才可获得锁执行。就像下面的例子,虽然调用了notifyAll()可是

  线程阻塞在了,只有等他醒来,等待线程才能重新获得锁。

   

synchronized (flag) {
	flag = "true";
	flag.notifyAll();
	try {
					
		Thread.sleep(10000);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }
}

    这篇博客  : notify / notifyAll / wait

猜你喜欢

转载自kainever7.iteye.com/blog/2218356