关于书中示例Java并发性在实践中的同步问题,清单4.12
我正在实践Java并发的一个例子,不理解为什么在下面的代码中需要一个并发安全容器
我看不出集装箱是怎么回事 “位置”的状态 可在施工后进行修改;因此,由于它是通过“unmodifiableMap”包装器发布的,在我看来,普通的HashMap就足够了
例如,它是并发访问的,但地图的状态只由读者访问,而不是由作者访问。映射中的值字段通过委托给“SafePoint”类进行同步,因此虽然点是可变的,但哈希键及其在映射中的关联值(对SafePoint实例的引用)永远不会更改
我认为我的困惑是基于藏品的具体状况
谢谢-迈克
清单4.12,实践中的Java并发, (该列表以.javahere的形式提供,也可以通过谷歌以章节形式提供)
//开始代码
@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;
}
}
//结束代码
# 1 楼答案
方法
setLocation
确实修改了映射的内容更新:我和一位同事讨论了这个问题,最后我们同意@Zwei Steinen的结论(+1对他:-)
请注意,除了他提到的,可见性也是一个问题。然而,在本例中,映射被声明为
final
,这保证了这一点# 2 楼答案
@Zwei,谢谢你的建议-Joe Bowbeer&;Tim Peierls(JCiP合著者)证实,从技术上讲,在这种情况下,普通的哈希映射就足够了。(尽管任何现实世界的设计都可能有额外的要求,这就需要并发映射)
原因是,基础地图是
-可从最后一个字段传递到
-自通过“getLocations()”发布后未更改(实际上它在ctor之后从未更改,但这不是必需的)
-结构合理
Joe指给我看了几篇非常好的博客文章,解释了java不变性的真正含义:
http://jeremymanson.blogspot.com/2008/04/immutability-in-java.html
http://jeremymanson.blogspot.com/2008/07/immutability-in-java-part-2.html
我会向那里的读者推荐一个完整的解释
谢谢
# 3 楼答案
你说得对。我认为这是JCiP中的一个错误。如果你想再确认一次,我建议你把它发到(它的)邮件列表上: http://gee.cs.oswego.edu/dl/concurrency-interest
就像你说的,地图没有被修改;修改该值不会导致在地图上出现任何“写入”
事实上,我的产品代码完全按照您的建议执行,我已经在上述邮件列表中询问了有关该代码的问题。JCiP的一位作者告诉我,可以对容器使用只读哈希映射
以下是我的代码的简化版本(无空检查等)(我最终使用了google collection的ImmutableMap):
它在极端负载下工作了很长一段时间