死锁之协作对象、锁粒度、开放调用

1、在两个协作对象之间,A对象中的a方法加锁,在a方法内部去调用B对象中加锁的b方法;B对象中的加锁方法c去调用A对象中的加锁方法d,协作对象之间产生死锁。

加锁的粒度应该适当,合理缩小锁粒度,降低死锁的产生,只对共享变量进行必要的同步。有原子性要求的方法例外。

2、示例代码:

/**
 * CooperatingDeadlock
 * 

* Lock-ordering deadlock between cooperating objects * * @author Brian Goetz and Tim Peierls */ public class CooperatingDeadlock { // Warning: deadlock-prone! class Taxi { @GuardedBy("this") private Point location, destination; private final Dispatcher dispatcher; public Taxi(Dispatcher dispatcher) { this.dispatcher = dispatcher; } public synchronized Point getLocation() { return location; } public synchronized void setLocation(Point location) { this.location = location; if (location.equals(destination)) dispatcher.notifyAvailable(this); } public synchronized Point getDestination() { return destination; } public synchronized void setDestination(Point destination) { this.destination = destination; } } class Dispatcher { @GuardedBy("this") private final Set<Taxi> taxis; @GuardedBy("this") private final Set<Taxi> availableTaxis; public Dispatcher() { taxis = new HashSet(); availableTaxis = new HashSet(); } public synchronized void notifyAvailable(Taxi taxi) { availableTaxis.add(taxi); } public synchronized Image getImage() { Image image = new Image(); for (Taxi t : taxis) image.drawMarker(t.getLocation()); return image; } } class Image { public void drawMarker(Point p) { } } }

Taxi中的同步方法setLocation调用了Dispatcher中的同步方法notifyAvailable,Dispatcher中的同步方法getImage调用了Taxi中的同步方法getLocation。当两个线程同时分别从taxi和dispatcher中进行调用时,会产生死锁。

在持有锁的方法中调用外部方法时需要注意,是否会产生死锁或阻塞。

3、如果调用某个方法时不需要持有锁,这种调用被称为开放调用。使用开放调用,缩小锁粒度,只对共享变量进行同步,优化之后代码如下:

/**
 * CooperatingNoDeadlock
 * 

* Using open calls to avoiding deadlock between cooperating objects * * @author Brian Goetz and Tim Peierls */ class CooperatingNoDeadlock { @ThreadSafe class Taxi { @GuardedBy("this") private Point location, destination; private final Dispatcher dispatcher; public Taxi(Dispatcher dispatcher) { this.dispatcher = dispatcher; } public synchronized Point getLocation() { return location; } public synchronized void setLocation(Point location) { boolean reachedDestination; synchronized (this) { this.location = location; reachedDestination = location.equals(destination); } if (reachedDestination) dispatcher.notifyAvailable(this); } public synchronized Point getDestination() { return destination; } public synchronized void setDestination(Point destination) { this.destination = destination; } } @ThreadSafe class Dispatcher { @GuardedBy("this") private final Set<Taxi> taxis; @GuardedBy("this") private final Set<Taxi> availableTaxis; public Dispatcher() { taxis = new HashSet(); availableTaxis = new HashSet(); } public synchronized void notifyAvailable(Taxi taxi) { availableTaxis.add(taxi); } public Image getImage() { Set<Taxi> copy; synchronized (this) { copy = new HashSet(taxis); } Image image = new Image(); for (Taxi t : copy) image.drawMarker(t.getLocation()); return image; } } class Image { public void drawMarker(Point p) { } } }


你可能感兴趣的:(并发编程,Java,Java并发实战-学习笔记)