Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用threadsafe集合的多线程_Java_Multithreading - Fatal编程技术网

Java 使用threadsafe集合的多线程

Java 使用threadsafe集合的多线程,java,multithreading,Java,Multithreading,我不明白下面的代码片段是如何实现线程安全的 class MapUser { Map<String,Integer> map = new ConcurrentHashMap<String,Integer> public void addToMap(String str, Integer val){ if(checkMagicString(str)){ map.put(str,val); } }

我不明白下面的代码片段是如何实现线程安全的

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
    }
}
类映射用户{
Map Map=新的ConcurrentHashMap
公共void addToMap(字符串str,整数val){
如果(检查magicstring(str)){
地图放置(str,val);
}
}
私有布尔校验字符串(字符串str){
//检查魔法的一些逻辑
//该逻辑涉及对字符串参数str的操作,即subString、toCharArray等
}
}
注意addToMap方法由多个线程并发调用。我想确保线程安全性得到维护。通过使用ConcurrentHashMap,我可以确保线程将安全地向其添加值

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

即使您将
checkMagicString
设置为原子,它也不会使序列成为原子

if(checkMagicString(str)){
   map.put(str,val);
}
原子,因为一个线程可以在
if
检查和
map.put
调用之间中断,因此可能会导致两个线程插入相同的字符串。您需要锁定整个序列以确保安全


编辑:如果上述行为是可接受的(即两个线程插入同一个键并覆盖该值)而且
checkMagicString
不在共享状态下运行,那么您的代码就可以正常运行。

如果您想要的是原子操作,那么在这种情况下,最好确保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您所拥有的将是“线程安全的”,但这可能会有所帮助。

我假设您正在访问
checkMagicString
内部的
映射?如果没有,那么你很好。如果你是,那么请编辑你的帖子来展示这一点。这实际上取决于checkMagicString在做什么。只要它不访问映射,这两个操作就不必是原子操作来维护线程安全。@assylias:这两个操作不需要,但顺序应该是原子操作,因为我假设他不希望两个线程放置相同的字符串。你的意思是使用同步的addToMap方法吗?如果这是必需的,那么多线程有什么好处?@Tudor如果checkMagicString不访问映射,那么没有什么可以阻止连续两次调用将同一字符串放入映射中两次。因此,使这两个操作原子化并没有什么区别(但增加了不必要的争用)。@assylias:我同意,我是说,不管
checkMagicString
s原子性如何,结果序列都不会是原子的。