我正在研究Java Concurrency in Practice中的一个示例,我不明白为什么在以下代码中需要并发安全容器.
我没看到容器怎么样
“地点”的状态
施工后可以修改;因为它是通过’unmodifiableMap’包装器发布的,所以在我看来普通的HashMap就足够了.
EG,它是同时访问的,但地图的状态只能由读者访问,不能由作者访问.地图中的值字段通过委托到“SafePoint”类同步,因此虽然这些点是可变的,但是地图中的哈希键及其关联值(对SafePoint实例的引用)永远不会改变.
我认为我的困惑是基于集合的状态究竟是什么.
谢谢!! -麦克风
代码清单4.12,Java Concurrency in Practice,
(此列表以.java here的形式提供,也可通过google以章节形式提供)
/////////////开始编码
@ThreadSafe
public class PublishingVehicleTracker {
private final Map<String, SafePoint> locations;
private final Map<String, SafePoint> unmodifiableMap;
public PublishingVehicleTracker(
Map<String, SafePoint> locations) {
this.locations
= new ConcurrentHashMap<String, SafePoint>(locations);
this.unmodifiableMap
= Collections.unmodifiableMap(this.locations);
}
public Map<String, SafePoint> getLocations() {
return unmodifiableMap;
}
public SafePoint getLocation(String id) {
return locations.get(id);
}
public void setLocation(String id, int x, int y) {
if (!locations.containsKey(id))
throw new IllegalArgumentException(
"invalid vehicle name: " + id);
locations.get(id).set(x, y);
}
}
//监视受保护的帮助程序类
@ThreadSafe
public class SafePoint {
@GuardedBy("this") private int x, y;
private SafePoint(int[] a) { this(a[0], a[1]); }
public SafePoint(SafePoint p) { this(p.get()); }
public SafePoint(int x, int y) {
this.x = x;
this.y = y;
}
public synchronized int[] get() {
return new int[] { x, y };
}
public synchronized void set(int x, int y) {
this.x = x;
this.y = y;
}
}
///////////结束代码
解决方法:
你是对的.我认为这是JCiP中的一个错误.如果您想要双重确定,我建议您将其发布到(其)邮件列表:
http://gee.cs.oswego.edu/dl/concurrency-interest
就像你说的那样,地图没有修改;修改值不会导致地图上的任何“写入”.
事实上,我的生产代码完全符合您的建议,我在上述邮件列表中询问了有关该代码的问题. JCiP的作者之一告诉我,可以使用容器的只读散列图.
这是我的代码的简化版本(无空检查等)(我最终使用google-collection的ImmutableMap.):
class Sample {
private final ImmutableMap<Long, AtomicReference<Stuff>> container;
Sample(){
this.container = getMap();
}
void setStuff(Long id, Stuff stuff){
AtomicReference<Stuff> holder = container.get(id);
holder.set(stuff);
}
}
它在极端负载下工作了很长时间.