我不明白下面的代码片段如何可以使线程安全。
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方法中的地图。
答案 0 :(得分:2)
即使你确实使checkMagicString
成为原子,它也不会产生序列
if(checkMagicString(str)){
map.put(str,val);
}
atomic,因为线程可以在if
检查和map.put
调用之间中断,因此最终会有两个线程插入相同的字符串。您需要锁定整个序列才能安全。
编辑:如果以上是可接受的行为(即两个线程插入相同的密钥并覆盖该值)并且checkMagicString
不能在共享状态下运行,那么您的代码就可以了是
答案 1 :(得分: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你所拥有的将是“线程安全的”,但也许这会有所帮助。