为什么来自 'Concurrency in practice' 的 CooperatingNoDeadlock 对同一个监视器使用双重同步?
Why CooperatingNoDeadlock from 'Concurrency in practice' use double synchronized with same monitor?
在书中 java concurrency in practice 你可以找到以下代码(10.6):
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<Taxi>();
availableTaxis = new HashSet<Taxi>();
}
public synchronized void notifyAvailable(Taxi taxi) {
availableTaxis.add(taxi);
}
public Image getImage() {
Set<Taxi> copy;
synchronized (this) {
copy = new HashSet<Taxi>(taxis);
}
Image image = new Image();
for (Taxi t : copy)
image.drawMarker(t.getLocation());
return image;
}
}
class Image {
public void drawMarker(Point p) {
}
}
}
让我们研究 setLocation
方法:
public synchronized void setLocation(Point location) { //first synchronized
boolean reachedDestination;
synchronized (this) { // second synchronized
this.location = location;
reachedDestination = location.equals(destination);
}
if (reachedDestination)
dispatcher.notifyAvailable(this);
}
}
我没看懂,还是同一台显示器双同步没用?
这段代码是我在书中找到的,你可以在这里找到它:
这是一个错误。像这样在同一个监视器上嵌套同步是没有用的。
errata引用了这个列表,"p.214: In Listing 10.6, Taxi.setLocation
should not be a synchronized method. (The synchronized block in its body is correct, however.)"
请注意,如果将同步放在块上,则当出租车不在目的地时,可以通知调度员有可用的出租车。这似乎是错误的,但在这种特定情况下也许还有其他措施可以解决这个问题。
在书中 java concurrency in practice 你可以找到以下代码(10.6):
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<Taxi>();
availableTaxis = new HashSet<Taxi>();
}
public synchronized void notifyAvailable(Taxi taxi) {
availableTaxis.add(taxi);
}
public Image getImage() {
Set<Taxi> copy;
synchronized (this) {
copy = new HashSet<Taxi>(taxis);
}
Image image = new Image();
for (Taxi t : copy)
image.drawMarker(t.getLocation());
return image;
}
}
class Image {
public void drawMarker(Point p) {
}
}
}
让我们研究 setLocation
方法:
public synchronized void setLocation(Point location) { //first synchronized
boolean reachedDestination;
synchronized (this) { // second synchronized
this.location = location;
reachedDestination = location.equals(destination);
}
if (reachedDestination)
dispatcher.notifyAvailable(this);
}
}
我没看懂,还是同一台显示器双同步没用?
这段代码是我在书中找到的,你可以在这里找到它:
这是一个错误。像这样在同一个监视器上嵌套同步是没有用的。
errata引用了这个列表,"p.214: In Listing 10.6, Taxi.setLocation
should not be a synchronized method. (The synchronized block in its body is correct, however.)"
请注意,如果将同步放在块上,则当出租车不在目的地时,可以通知调度员有可用的出租车。这似乎是错误的,但在这种特定情况下也许还有其他措施可以解决这个问题。