活跃性(Liveness)

   一个并发应用能够及时执行任务的特性称为活跃性,这一节讲述最常见的一种活跃性问题–死锁,并将简单的介绍另外两种活跃性问题,分别为饥饿和活锁。

死锁(Deadlock)
   死锁描述的是这样一种情景,当两个或者多个线程处于永远阻塞状态,并等待对方,如下一个例子:

A和B是朋友,并且有良好的礼仪习惯。礼节中有一项规则,就是当你向朋友躬身时,你必须一直保持弓着状态以让你的朋友有机会躬身回礼,不幸的是,这个规则不会导致两个朋友同时向对方躬身可能性,以下例子,死锁,模拟了这种可能性:

public class Deadlock{
    static class Friend{
        private final String name;
        pulibc Friend(String name){
            this.name = name;
        }

        public 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 a = new Friend("a");
    final Friend b = new Friend("b");
    new Thread(new Runnable(){
        public void run(){
            a.bow(b);
        }
    }).start();

    new Thread(new Runnable(){
        public void run(){
            b.bow(a);
        }
    }).start();
}
} 

   两个线程试图调用bowBack方法将会都处于阻塞状态,没有一个阻塞会终止,因为每个线程都等待这对方退出bow方法,这时,死锁就发生了。

饥饿和活锁
   比起死锁,饥饿和活锁更少发生,但是它们仍然是每个并发软件会遇到的问题。

   饥饿(Starvation)
   它描述了这样一个场景,当一个线程不能获取定期访问来共享资源而不能继续运行,在共享资源被饥渴线程长期占有时,就会发生饥饿。例如,加速一个对象提供一个要花很长时间才能返回结果的同步方法,如果一个线程频繁调用这个方法,其它线程也需要频繁调用同步进入同一个对象的方法时,阻塞就发生了。

   活锁(Livelock)
   一个线程经常对另外一个线程的响应做响应的处理,如果线程的另外一个动作同样是对另外一个线程响应而发生,结果可能导致活锁,类似死锁,发生活锁的线程不能更进一步的处理,然而,线程并没有被阻塞,他们只是忙碌于响应对方而重复工作,这类似于两个人在走廊中试图让对方,a移向左以让b通过,而b移向右以让a通过,可以看到,他们仍然互相阻塞,a移动到右边,而b移动到左边,结果他们仍然还是阻塞着。。。

你可能感兴趣的:(java,deadlock)