您的位置:首页 > 编程语言 > Java开发

Java并发编程(四)活跃度

2016-08-15 12:07 357 查看

4. 活跃度

一个并发应用及时执行的能力称作活跃度。本节介绍最常见的活跃度问题,死锁,然后继续简单介绍两种其他的活跃度问题,饥饿和活锁。

4.1 死锁

死锁介绍了两个或者多个线程永远阻塞、彼此等待的情形。这是一个例子,

Alphonse和Gaston是朋友,并且彼此很有礼貌。一个礼貌的严格规定是,当你鞠躬的时候,你必须保持一直鞠躬,直到你朋友结束鞠躬。然而,这却没有考虑两个朋友可能在相同时刻都向对方鞠躬。这个示例应用,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();
}
}


当Deadlock运行时,当两个线程尝试调用bowBack时,极有可能阻塞。两个阻塞都不会结束,因为两个线程都在等待另一个线程结束鞠躬。

4.2 饥饿和活锁

饥饿和活锁问题没有死锁那么常见,但是仍然是一个并发程序开发者需要考虑的问题。

4.2.1 饥饿

饥饿指的是线程无法访问共享数据,并且无法继续执行。当共享数据被线程长时间占有的时候,该现象就会发生。例如,假设一个对象提供了一个耗时比较长的同步化方法。如果一个线程频繁地调用该方法,其他需要频繁调用该方法的线程就会经常被阻塞。

4.2.2 活锁

一个线程经常对另一个线程作出回应。如果另一个线程对其他线程又要作出回应,那么活锁就可能发生。和死锁一样,活锁也会导致程序无法继续运行。然而,线程并没有被阻塞——它们仅仅忙于回应其他线程无法继续执行任务。这类似于两个人在一个走廊中过路:Alphonse移到左边让Gaston通过,Gaston移到右边让Alphonse通过。由于他们被彼此阻塞,Alphonse移到右边,Gaston移到左边。他们又会发生阻塞,一直循环下去。。。

文章翻译自Java Tutorials, Concurrency,翻译难免会有纰漏,欢迎读者讨论指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 并发 编程 线程