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 从缓存获取的集合中的线程安全性_Java_Multithreading_Thread Safety - Fatal编程技术网

Java 从缓存获取的集合中的线程安全性

Java 从缓存获取的集合中的线程安全性,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我偶然发现了以下代码: public static final Map<String, Set<String>> fooCacheMap = new ConcurrentHashMap<>(); publicstaticfinalmap fooCacheMap=newconcurrenthashmap(); 通过rest控制器方法访问此缓存: public void fooMethod(String fooId) { Set<String&g

我偶然发现了以下代码:

public static final Map<String, Set<String>> fooCacheMap = new ConcurrentHashMap<>();
publicstaticfinalmap fooCacheMap=newconcurrenthashmap();
通过rest控制器方法访问此缓存:

public void fooMethod(String fooId) {
    Set<String> fooSet = cacheMap.computeIfAbsent(fooId, k -> new ConcurrentSet<>());
    //operations with fooSet
}
公共void foodmethod(字符串fooId){
Set fooSet=cacheMap.computeIfAbsent(fooId,k->newconcurrentset());
//使用fooSet的操作
}

ConcurrentSet
真的有必要吗?当我确定只能通过此方法访问集合时?

当您在控制器中使用它时,多个线程可以同时调用您的方法(例如,多个并行请求可以调用您的方法)


由于此方法看起来没有以任何方式同步,因此这里可能需要ConcurrentSet。

当您在控制器中使用它时,多个线程可以同时调用您的方法(例如,多个并行请求可以调用您的方法)

由于此方法看起来没有任何同步方式,因此这里可能需要ConcurrentSet

ConcurrentSet真的有必要吗

可能,可能不是。我们不知道这个代码是如何使用的

但是,假设它是以多线程方式使用的(特别是:两个线程可以同时调用
fooMethod
),则是

ConcurrentHashMap
中的原子性仅保证每次调用
ComputeFabSent
。一旦完成,锁就被释放,其他线程就可以调用该方法。因此,对返回值的访问不是原子的,因此在访问该值时可以得到线程推断

关于“我需要` ConcurrentSet'吗?”?否:您可以这样做,以便对集合的访问是原子的:

cacheMap.compute(fooId, (k, fooSet) -> {
  if (fooSet == null) fooSet = new HashSet<>();
  // Operations with fooSet
  return v;
});
cacheMap.compute(fooId,(k,fooSet)->{
如果(fooSet==null)fooSet=newhashset();
//使用fooSet的操作
返回v;
});
ConcurrentSet真的有必要吗

可能,可能不是。我们不知道这个代码是如何使用的

但是,假设它是以多线程方式使用的(特别是:两个线程可以同时调用
fooMethod
),则是

ConcurrentHashMap
中的原子性仅保证每次调用
ComputeFabSent
。一旦完成,锁就被释放,其他线程就可以调用该方法。因此,对返回值的访问不是原子的,因此在访问该值时可以得到线程推断

关于“我需要` ConcurrentSet'吗?”?否:您可以这样做,以便对集合的访问是原子的:

cacheMap.compute(fooId, (k, fooSet) -> {
  if (fooSet == null) fooSet = new HashSet<>();
  // Operations with fooSet
  return v;
});
cacheMap.compute(fooId,(k,fooSet)->{
如果(fooSet==null)fooSet=newhashset();
//使用fooSet的操作
返回v;
});

使用并发映射不能保证线程安全。对映射的添加需要在同步块中执行,以确保两个线程不会尝试向映射添加相同的密钥。因此,实际上并不需要并发映射,特别是因为映射本身是静态的和最终的。此外,如果代码修改了映射内的集合(看起来很可能),那么也需要同步

正确的方法是查看地图是否有钥匙。如果不存在,请输入同步块并再次检查该键。这保证了在每次不输入同步块的情况下密钥不存在


集合修改通常也应该发生在同步块中

使用并发映射不能保证线程安全。对映射的添加需要在同步块中执行,以确保两个线程不会尝试向映射添加相同的密钥。因此,实际上并不需要并发映射,特别是因为映射本身是静态的和最终的。此外,如果代码修改了映射内的集合(看起来很可能),那么也需要同步

正确的方法是查看地图是否有钥匙。如果不存在,请输入同步块并再次检查该键。这保证了在每次不输入同步块的情况下密钥不存在


集合修改通常也应该发生在同步块中

问题不在于是否仅使用此方法访问该集,而在于两个线程是否可以同时访问该集。您可以在多个线程中并行运行此代码,谁知道呢。“当我确定只能使用此方法访问集合时?”但您不知道,因为
fooCacheMap
public
。问题不在于是否仅使用此方法访问集合,而在于两个线程是否可以同时访问集合。您可以在多个线程中并行运行此代码,谁知道呢。“当我确定只能通过此方法访问集合时?”但您不知道,因为
fooCacheMap
public
。您可以甚至应该在不使用同步块的情况下添加到ConcurrentHashMap。ConcurrentHashMap的实现保证了线程安全。使用synchronized锁定它只会降低性能。“确保两个线程不会尝试向映射添加相同的密钥”是相关的要点。您可以甚至应该在不使用synchronized块的情况下添加ConcurrentHashMap。ConcurrentHashMap的实现保证了线程安全。用synchronized锁定它只会降低性能。“确保两个线程不会尝试向映射添加相同的密钥”是相关的要点。