4

I have a parallel stream in which I'm using a Map to mutate the elements.

Map<Long, List<MyItem>> hashmap = foo.getMap();

itemStream.parallel()
  .filter(Objects::nonNull)
  .forEach(item -> setProperties(hashmap, item));

The method 'setProperties()' takes the map and item, and performs a get using item and then sets some attributes of the item.

What I want is for the getting/property setting to be done atomically. So that two threads can't perform a get on the same key and have property updates be interleaved.

private void setProperties(Map<Long, List<Item>> map, Item item) {
    long id = item.getID();
    List<Object1> items = map.get(id);
    for (Object1 ob : items) {
            ob.setId(item.getFloorId());
            ob.setPath(item.getPath());
            ob.setTypeName(item.getTypeName());
    }
}

Also a bit concerned about the latency hit and whether this sort of parallelization will really have a benefit vs the existing single threaded approach.

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
SS'
  • 819
  • 1
  • 8
  • 18
  • If your `itemStream` doesn't have duplicates (or duplicated `ID`s) then there will be no interleaving `get()` calls for the same key – Ivan Jul 24 '18 at 14:45
  • Don't have that guarantee, may have duplicate IDs @Ivan – SS' Jul 24 '18 at 14:47
  • @JacobG. at leas tin Java 8 in CHM `get()` is a non-blocking operation – Ivan Jul 24 '18 at 14:52
  • 1
    Do these items with the same ID contain contradicting data? If so, how do you want to solve these contradictions? If not, what’s stopping you from filtering out these duplicate IDs before performing the operation? – Holger Jul 24 '18 at 17:09

1 Answers1

7

Synchnorising the Map or the get from it has no benefit, because the map is not being altered so there’s no race condition.

You need to synchronise the updates so they happen all-at-once:

for (Object1 ob : items) {
    synchronized (ob) {
        ob.setId(item.getFloorId());
        ob.setPath(item.getPath());
        ob.setTypeName(item.getTypeName());
    }
}

This will have very little impact on performance, because these days synchronising introduces very little overhead and you will only block if the same Item is being operated on.

Bohemian
  • 412,405
  • 93
  • 575
  • 722