在安全性和活跃性之间通常存在着某种制衡

 

一、死锁

定义:在线程A持有锁L并想获得锁M的同时,线程B持有锁M并尝试获得锁L,线程AB均不会释放自己的锁,那么这两个线程将永远地等待下去

在数据库系统的设中考虑了检测死锁以及从死锁中恢复。JVM没有办法解决死锁,只能在编程和测试时注意不要让死锁发生

1、锁顺序死锁——两个线程试图以不同的顺序来获得相同的锁

第十章:避免活跃性危险——Java并发编程实战

解决:如果所有线程以固定的顺序来获得锁,那么在程序中就不会出现锁顺序死锁问题。

2、动态的锁顺序死锁

1 A: transferMoney(myAccount, yourAccount, 10);
2 B: transferMoney(yourAccount, myAccount, 20);

使用Account中包含的唯一的不可变的并且具备可比性的键值或计算HashCode作为加锁顺序的依据

3、在协作对象间发生死锁

如果在持有锁时调用某个外部方法,那么将出现活跃性问题。在这个外部方法中可能会获取其他锁(这可能会产生死锁),或者阻塞时间过长,导致其他线程无法及时获得当前被持有的锁。

 1 class Taxi {
 2         @GuardedBy("this") private Point location, destination;
 3         private final Dispatcher dispatcher;
 4 
 5         public Taxi(Dispatcher dispatcher) {
 6             this.dispatcher = dispatcher;
 7         }
 8 
 9         public synchronized Point getLocation() {
10             return location;
11         }
12 
13         public synchronized void setLocation(Point location) {
14             this.location = location;
15             if (location.equals(destination))
16                 dispatcher.notifyAvailable(this);
17         }
18 
19         public synchronized Point getDestination() {
20             return destination;
21         }
22 
23         public synchronized void setDestination(Point destination) {
24             this.destination = destination;
25         }
26     }
27 
28     class Dispatcher {
29         @GuardedBy("this") private final Set<Taxi> taxis;
30         @GuardedBy("this") private final Set<Taxi> availableTaxis;
31 
32         public Dispatcher() {
33             taxis = new HashSet<Taxi>();
34             availableTaxis = new HashSet<Taxi>();
35         }
36 
37         public synchronized void notifyAvailable(Taxi taxi) {
38             availableTaxis.add(taxi);
39         }
40 
41         public synchronized Image getImage() {
42             Image image = new Image();
43             for (Taxi t : taxis)
44                 image.drawMarker(t.getLocation());
45             return image;
46         }
47     }
举例:在协作对象间发生死锁

taxi.setLocation(location) 和dispatcher.notifyAvailable(taxi)同时调用时会发生锁顺序死锁

4、开放调用——在调用某个方法时不需要持有锁

在程序中应尽量使用开放调用。与那些在持有锁时调用外部方法的程序相比,更易于对依赖于开放调用的程序进行死锁分析

 1 class Taxi {
 2         @GuardedBy("this") private Point location, destination;
 3         private final Dispatcher dispatcher;
 4 
 5         public Taxi(Dispatcher dispatcher) {
 6             this.dispatcher = dispatcher;
 7         }
 8 
 9         public synchronized Point getLocation() {
10             return location;
11         }
12 
13         public synchronized void setLocation(Point location) {
14             boolean reachedDestination;
15             synchronized (this) {
16                 this.location = location;
17                 reachedDestination = location.equals(destination);
18             }
19             if (reachedDestination)
20                 dispatcher.notifyAvailable(this);
21         }
22 
23         public synchronized Point getDestination() {
24             return destination;
25         }
26 
27         public synchronized void setDestination(Point destination) {
28             this.destination = destination;
29         }
30     }
31 
32     @ThreadSafe
33     class Dispatcher {
34         @GuardedBy("this") private final Set<Taxi> taxis;
35         @GuardedBy("this") private final Set<Taxi> availableTaxis;
36 
37         public Dispatcher() {
38             taxis = new HashSet<Taxi>();
39             availableTaxis = new HashSet<Taxi>();
40         }
41 
42         public synchronized void notifyAvailable(Taxi taxi) {
43             availableTaxis.add(taxi);
44         }
45 
46         public Image getImage() {
47             Set<Taxi> copy;
48             synchronized (this) {
49                 copy = new HashSet<Taxi>(taxis);
50             }
51             Image image = new Image();
52             for (Taxi t : copy)
53                 image.drawMarker(t.getLocation());
54             return image;
55         }
56     }
举例:修改上例使用开放调用避免死锁

相关文章:

  • 2021-10-01
  • 2022-12-23
  • 2021-09-22
  • 2022-12-23
  • 2021-11-02
  • 2022-12-23
  • 2021-06-09
  • 2021-11-30
猜你喜欢
  • 2021-07-24
  • 2021-08-24
  • 2021-11-10
  • 2022-12-23
  • 2021-07-27
  • 2021-09-23
  • 2021-06-29
相关资源
相似解决方案