一、基本概念
Synchronized 合作关系,和Synchronized 互斥块锁
相同:反正是锁住后面的代码块,cpu单独执行。
不同:Synchronized,wait,notifyAll 合作关系,干完活后指定别人去干,一看见这个表示这活干不下去了,必须等别人干完,发消息后,自己才能继续干完。
Synchronized 互斥,干完活后,没有指定别人干,一堆人通过竞争才能拥有共享资源。
*** Synchronized 合作关系:容易发生死锁,书上几乎推荐所有的wait()最好包在while(){} 里面,由main()线程的中断来终止所有干活线程。
例如装修:
正常顺序是:装修工人刮完墙,等待收垃圾的人收走垃圾,收垃圾的人等待装修工人回个信表示垃圾已经收完。
死锁:收垃圾的人先收走垃圾,等待装修工人回个信表示垃圾已经收完,但是装修工人等待收走垃圾。
就存在装修工人等收垃圾的人,收垃圾的人带装修工人,两人一直都在等。
notifyAll():唤醒多个干活线程
notify():唤醒一个干活线程
二、例子:下面只是成功拿到钱的一个例子,只是为了说明wait() notifyAll的走向流程,并不涉及死锁状态。
去银行取钱,发现钱不够,叫家里人寄点过来,于是在银行等(wai()),家里人寄钱过来后通知我(notify())且也在银行等我回信(wait)才离开。
1、图形(一),这里是要钱方先执行,因为有两个干活线程处于等待状态,所以程序里面用notifyAll()唤醒,就是怕出现死锁现象。
2、图形(二)
三、代码
package concurrency; import java.util.concurrent.*; import static net.mindview.util.Print.*; class Money { //默认是没钱。 private boolean hasMoney = false; //发消息告诉要钱方已经寄钱了。 public synchronized void hasMoneyed() { hasMoney = true; // notifyAll(); } //要钱方发消息告诉寄钱方已经收到钱了。 public synchronized void received() { hasMoney = false; notifyAll(); } //hasMoney == false表示账上没钱,等待寄钱方寄钱 public synchronized void waitForMoney() throws InterruptedException { printnb(Thread.currentThread().getName()+"得waitForMoney()锁! "); while (hasMoney == false) wait(); } //hasMoney == true账上有钱,寄钱方等待要钱方发消息表示钱已经收到 public synchronized void waitForReceived() throws InterruptedException { printnb(Thread.currentThread().getName()+"得waitForReceived锁! "); while (hasMoney == true) wait(); } } class SendMoney implements Runnable { private Money money; public SendMoney(Money c) { money = c; } /**寄钱 */ public void run() { try { printnb(Thread.currentThread().getName()+"现在准备寄钱! "); TimeUnit.MILLISECONDS.sleep(200); printnb(Thread.currentThread().getName()+"开始发消息给要钱方,收到寄钱消息! "); money.hasMoneyed(); printnb(Thread.currentThread().getName()+"发消息给要钱方,开始寄钱! "); money.waitForReceived(); } catch (InterruptedException e) { print("寄钱失败"); } print(Thread.currentThread().getName()+"寄钱成功!"); } } /**要钱 */ class WaitMoney implements Runnable { private Money money; public WaitMoney(Money c) { money = c; } public void run() { try { printnb(Thread.currentThread().getName()+"账号没钱,等待寄钱方寄钱! "); money.waitForMoney(); TimeUnit.MILLISECONDS.sleep(200); printnb(Thread.currentThread().getName()+"等200秒后,通知寄钱方已经收到钱! "); money.received(); } catch (InterruptedException e) { print("要钱失败"); } print(Thread.currentThread().getName()+"要钱成功! "); } } public class WaxOMatic { public static void main(String[] args) throws Exception { Money car = new Money(); ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new WaitMoney(car)); exec.execute(new SendMoney(car)); //最后加的,防止死锁。 TimeUnit.SECONDS.sleep(200); exec.shutdown(); } } |
输出结果:
pool-1-thread-1账号没钱,等待寄钱方寄钱!
pool-1-thread-1得waitForMoney()锁!
pool-1-thread-2现在准备寄钱!
pool-1-thread-2开始发消息给要钱方,收到寄钱消息! pool-1-thread-2发消息给要钱方,开始寄钱!
pool-1-thread-2得waitForReceived锁!
pool-1-thread-1等200秒后,通知寄钱方已经收到钱! pool-1-thread-1要钱成功!
pool-1-thread-2寄钱成功!