Java Concurrency 之四
活性(Liveness)
并发程序能及时(in a timely manner)执行的能力叫作它的活性。本节描述了最常见的一种活性问题:死锁(deadlock)。然后简单描述了另外两个活性问题, 饥饿(starvation)和活锁(livelock)。
死锁
死锁描述了两个或更多的线程因为要等待彼此释放锁而永远阻塞。这里有个例子:
Alphonse和Gaston是朋友,很重视礼节(great believers in courtesy)。一个很重要的约定是,当向一个朋友鞠躬时,如果朋友不向你回礼(鞠躬)你就不能直身。不幸的是,如果两个人同时向对方鞠躬就有问题了。在本例中,Deadlock 描述了这种可能:
public class Deadlock { static class Friend { private final String name; public Friend(String name) { this.name = name; } public String getName() { return this.name; } public synchronized void bow(Friend bower) { System.out.format("%s: %s" + " has bowed to me!%n", this.name, bower.getName()); bower.bowBack(this); } public synchronized void bowBack(Friend bower) { System.out.format("%s: %s" + " has bowed back to me!%n", this.name, bower.getName()); } } public static void main(String[] args) { final Friend alphonse = new Friend("Alphonse"); final Friend gaston = new Friend("Gaston"); new Thread(new Runnable() { public void run() { alphonse.bow(gaston); } }).start(); new Thread(new Runnable() { public void run() { gaston.bow(alphonse); } }).start(); }}package com.test.livelock;public class Gentleman extends Thread {private String manName;private Gentleman anotherGentleman;public Gentleman(String name,Gentleman anotherGentleman){this.manName=name;this.anotherGentleman=anotherGentleman;}public Gentleman() {}void walkwith(Gentleman anotherGentleman){try {System.out.println(manName+" says :i pass "+anotherGentleman.getManName());anotherGentleman.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(manName+" says : i passed");}private String getManName() {return manName;}public Gentleman getAnotherGentleman() {return anotherGentleman;}public void setAnotherGentleman(Gentleman anotherGentleman) {this.anotherGentleman = anotherGentleman;}public void setManName(String manName) {this.manName = manName;}@Overridepublic void run() {walkwith(anotherGentleman);}public static void main(String[] args) {Gentleman jay=new Gentleman();Gentleman jj=new Gentleman();jay.setAnotherGentleman(jj);jj.setAnotherGentleman(jay);jay.setManName("Jay");jj.setManName("JJ");jay.start();jj.start();}}