0

我不明白如何使下面的代码片段成为线程安全的。

class MapUser {
    Map<String,Integer> map = new ConcurrentHashMap<String,Integer>

    public void addToMap(String str, Integer val){
        if(checkMagicString(str)){
            map.put(str,val);
        }
    }

    private boolean checkMagicString(String str){
        //some logic to check Magic
        //this logic involved operation on the String parameter str i.e. subString,toCharArray etc
    }
}

注意 addToMap 方法被多个线程同时调用。我想确保维护线程安全。通过使用 ConcurrentHashMap,我可以确保线程安全地将值添加到其中。

但是我不明白方法 checkMagicString(String str) 如何保持线程安全?是让它同步的唯一方法吗?还是应该使调用方方法 addToMap 同步?请注意,我没有在 checkMagicString 方法中访问地图。

4

2 回答 2

2

即使你做checkMagicString原子,它不会使序列

if(checkMagicString(str)){
   map.put(str,val);
}

原子的,因为线程可以在if检查和map.put调用之间被中断,因此您最终可能会有两个线程插入相同的字符串。您需要锁定整个序列以确保安全。

编辑:如果上述行为是可接受的(即两个线程插入相同的键并覆盖值)并且checkMagicString不对共享状态进行操作,那么您的代码就可以了。

于 2012-07-10T17:01:10.617 回答
0

如果您想要的是原子操作,那么在这种情况下最好的办法是确保 checkMagicStr 是原子的,并在地图上使用原子操作:

boolean done = false;
while(!done) {
  Integer oldVal = map.get(str);
  if (checkMagicStr(str) {
    if (oldVal != null) {
      done = value == map.replace(str, val, oldVal); // otherwise try again...
    } else {
      done = null == map.putIfAbsent(str, val); // otherwise try again...
    }
  } else {
    done = true; // there's nothing to do...
  }
}

您可能希望对该 while 循环进行限制,并在它被命中时抛出异常,因为这可能会在高度并发的系统上永远运行。从你的问题中不清楚为什么这一切都是必要的,b/c 你所拥有的将是“线程安全的”,但也许这无论如何都会有所帮助。

于 2012-07-10T17:19:19.910 回答