Book Example Question - Java Concurrency in Practice Listing 4.12

I am working on an example in Java Concurrency in practice and don’t understand why a container is needed while being used in the following code.

I do not see how the container's “location” state can be changed after construction; since it is published through the "unmodifiableMap" shell, it seems to me that the usual HashMap is enough.

EG, it is addressed at the same time, but the state of the card is available only to readers, not writers. The value fields on the map are synchronized by delegation to the SafePoint class, so when the points are mutable, the keys for the hash and their associated values ​​(links to SafePoint instances) on the map never change.

I think my confusion is based on exactly what state of the collection is in the problem.

Thank!! -Mike

Listing 4.12, Java Concurrency in practice, (this declaration is available as .java here , as well as in the form of a chapter via google)

///////////// start of code

@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);
  }
}

// control the protected helper class

@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;
}

}

/////////// end code

+3
source share
3 answers

You're right. I think this is a bug in JCiP. If you want to be confident, I suggest you publish it on your mailing list at: http://gee.cs.oswego.edu/dl/concurrency-interest

As you said, the map does not change; changing the value does not lead to any "recording" on the map.

, , , . JCiP , .

( ..) ( google- 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);
    }
}

.

+4

setLocation .

: , @Zwei Steinen (+1 : -).

, , , . final, .

+1

@Zwei, - ( JCiP) , -. ( , , , )

, - -
- 'getLocations()' ( ctor, )
-

Joe pointed me to a couple of very good blog posts explaining more about what java immutability really means:

http://jeremymanson.blogspot.com/2008/04/immutability-in-java.html
http://jeremymanson.blogspot.com/2008/07/immutability-in-java-part-2.html

I would call readers there for a full explanation.

Thank!

+1
source

Source: https://habr.com/ru/post/1739892/


All Articles