Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.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 如何使用get和put作为原子操作使并发哈希映射线程安全?_Java_Multithreading_Thread Safety_Guava_Atomicity - Fatal编程技术网

Java 如何使用get和put作为原子操作使并发哈希映射线程安全?

Java 如何使用get和put作为原子操作使并发哈希映射线程安全?,java,multithreading,thread-safety,guava,atomicity,Java,Multithreading,Thread Safety,Guava,Atomicity,我下面的方法是线程安全的吗?此方法位于Singleton类中 private static final Map<String, PreparedStatement> holder = new ConcurrentHashMap<>(); public BoundStatement getStatement(String cql) { Session session = TestUtils.getInstance().getSession(); P

我下面的方法是线程安全的吗?此方法位于Singleton类中

  private static final Map<String, PreparedStatement> holder = new ConcurrentHashMap<>();

  public BoundStatement getStatement(String cql) {
    Session session = TestUtils.getInstance().getSession();
    PreparedStatement ps = holder.get(cql);
    if(ps == null) { // If "ps" is already present in cache, then we don't have to synchronize and make threads wait.
        synchronized {
          ps = holder.get(cql);
          if (ps == null) {
            ps = session.prepare(cql);
            holder.put(cql, ps);
          }
        }
    }
    return ps.bind();
  }
private static final Map holder=new ConcurrentHashMap();
public BoundStatement getStatement(字符串cql){
会话会话=TestUtils.getInstance().getSession();
准备好的报表ps=持有者获取(cql);
如果(ps==null){//如果缓存中已经存在“ps”,那么我们就不必进行同步并让线程等待。
同步的{
ps=持有者获取(cql);
如果(ps==null){
ps=会话准备(cql);
持票人看跌期权(cql,ps);
}
}
}
返回ps.bind();
}
我正在使用Cassandra和datastax java驱动程序,因此我正在重用准备好的语句,这就是为什么我在这里缓存它。和


有没有更好的方法使我的
getStatement
方法线程安全(如果它是线程安全的)而不是像那样使用同步块?对于这类操作,还有其他线程安全的数据结构吗?我正在使用Java 7。

因为.putIfAbsent在Java 7中,所以您可以使用它:

 private static final ConcurrentHashMap<String, PreparedStatement> holder = new ConcurrentHashMap<>();

  public BoundStatement getStatement(String cql) {
    Session session = TestUtils.getInstance().getSession();
    PreparedStatement ps = holder.get(cql);
    if(ps == null) { // If "ps" is already present in cache, then we don't have to synchronize and make threads wait.

         if (holder.putIfAbsent(cql, session.prepare(cql)) != null) {
            // Someone else got there before, handle
         }
    }
    return ps.bind();
  }
私有静态最终ConcurrentHashMap持有者=新ConcurrentHashMap();
public BoundStatement getStatement(字符串cql){
会话会话=TestUtils.getInstance().getSession();
准备好的报表ps=持有者获取(cql);
如果(ps==null){//如果缓存中已经存在“ps”,那么我们就不必进行同步并让线程等待。
if(holder.putIfAbsent(cql,session.prepare(cql))!=null){
//以前有人到过那里,明白吗
}
}
返回ps.bind();
}

请注意,putIfAbsent在内部仍然使用相同的同步。

如果您希望执行某种形式的记忆,那么这是Java 7中最好/最简单的方法。Guava有一个可以使用的计算缓存实现,Java8在
Map
接口中有一个
ComputeFabSent
方法,但显然你在这里运气不好

如果你能像Alexey的回答所建议的那样,在一个空竞赛中创建对象,那将是最好的解决方案。如果不能,那么您的实现是线程安全且合理的


这是一种双重检查锁定的形式,但是,通过此实现,您可以使用CHM的
put
get
方法确保在订购前发生锁定。

啊,很抱歉,错过了这一点。您问题的标题有点离题。您不必使ConcurrentHashMap线程安全:它已经是线程安全的了。你在这里要做的是使你自己的代码线程安全。是的,我想你是对的。我应该在内部if块中做什么?如何处理?内部块意味着你同时准备了两个相同的cql,只有一个在地图上。如果你不在乎,就放下那块砖。如果是,请记录它或抛出错误。注意:
putIfAbsent
出现在
ConcurrentHashMap
上,而不是
Map
上。你需要更改字段声明。我正在看这个。是一样还是不同?