有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

关于书中示例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;
}

}

//结束代码


共 (3) 个答案

  1. # 1 楼答案

    方法setLocation确实修改了映射的内容

    更新:我和一位同事讨论了这个问题,最后我们同意@Zwei Steinen的结论(+1对他:-)

    请注意,除了他提到的,可见性也是一个问题。然而,在本例中,映射被声明为final,这保证了这一点

  2. # 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. # 3 楼答案

    你说得对。我认为这是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);
        }
    }
    

    它在极端负载下工作了很长一段时间