java - "putIfAbsent"在CHM中如何工作?

标签 java multithreading thread-safety guava concurrenthashmap

我正在使用 Cassandra 并使用 Datastax Java 驱动程序。我正在尝试通过缓存来重用准备好的语句。

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

  public BoundStatement getStatement(String cql) {
    Session session = TestUtils.getInstance().getSession();
    PreparedStatement ps = holder.get(cql);
    // no statement is cached, create one and cache it now.
    if (ps == null) {
      holder.putIfAbsent(cql, session.prepare(cql));
    }
    return ps.bind();
  }

Prepared StatementBoundStatement datastax java 驱动程序。

getStatement 方法将由多个线程调用,因此我必须确保它是线程安全的。我正在使用 Java 7。

如果我们得到两个相同的 cql 准备好的语句,putIfAbsent 会做什么?我的代码线程安全并且没有竞争条件吗?

更新:-

  public BoundStatement getStatement(String cql) {
    Session session = TestUtils.getInstance().getSession();
    PreparedStatement ps = holder.get(cql);
    // no statement is cached, create one and cache it now.
    if (ps == null) {
      synchronized (this) {
        ps = holder.get(cql);
        if (ps == null) {
          ps = session.prepare(cql);
          holder.put(cql, ps);
        }
      }
    }
    return ps.bind();
  }

最佳答案

您的代码存在竞争条件,可能会导致任何 cql 参数调用 session.prepare(cql) 两次(或更多次)。在这种情况下,putIfAbsent 并没有真正比普通的 put 提供任何优势。

如果您使用的是 Java 8,您可以高效地编写此代码,而无需使用以下命令创建重复项

PreparedStatement ps = holder.computeIfAbsent(cql, key -> session.prepare(key));

关于java - "putIfAbsent"在CHM中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40874129/

相关文章:

java - 如何逐行复制大数据文件?

java - 安卓多线程

java - 如果发生异常则退出 Java Callable

C# 如何确保用户提供线程安全对象来运行

java - 将数组作为线程安全参数传递时出现 ActionListener 错误

java.lang.ClassNotFoundException : sun. jdbc.odbc.JdbcOdbcDriver 发生异常。为什么?

java - 访问目录

java - 没有打印语句,循环看不到其他线程更改的值

java - 形式参数上的同步有什么作用?

php - 如何在 PHP 中禁用线程安全?