"putIfAbsent" 在 CHM 中如何工作?
How does "putIfAbsent" works in CHM?
我正在使用 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 Statement and BoundStatement 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();
}
您的代码存在竞争条件,可能会导致 session.prepare(cql)
被任何 cql
参数调用两次(或多次)。 putIfAbsent
在这种情况下并没有真正提供比普通 put
任何优势。
如果您使用的是 Java 8,您可以高效地编写此代码而无需使用
创建重复项
PreparedStatement ps = holder.computeIfAbsent(cql, key -> session.prepare(key));
你确实有竞争条件,但你的 putIfAbsent
可能仍然比纯 put
稍微好一点,因为它保留了旧的声明,所以在实际使用中从来没有两个实例。优势很小,因为它仅在出现竞争条件时才会显现。
它看起来像是 Double-checked locking 的一个版本。如果真的需要,只需在初始化周围放置一个同步块并重新检查。
我对缓存 PreparedStatement
持怀疑态度,因为它是可变的。对于同一个 cql
,您可能需要多个实例。这也是可行的,但你需要正确地获取和释放它们。
我正在使用 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 Statement and BoundStatement 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();
}
您的代码存在竞争条件,可能会导致 session.prepare(cql)
被任何 cql
参数调用两次(或多次)。 putIfAbsent
在这种情况下并没有真正提供比普通 put
任何优势。
如果您使用的是 Java 8,您可以高效地编写此代码而无需使用
创建重复项PreparedStatement ps = holder.computeIfAbsent(cql, key -> session.prepare(key));
你确实有竞争条件,但你的 putIfAbsent
可能仍然比纯 put
稍微好一点,因为它保留了旧的声明,所以在实际使用中从来没有两个实例。优势很小,因为它仅在出现竞争条件时才会显现。
它看起来像是 Double-checked locking 的一个版本。如果真的需要,只需在初始化周围放置一个同步块并重新检查。
我对缓存 PreparedStatement
持怀疑态度,因为它是可变的。对于同一个 cql
,您可能需要多个实例。这也是可行的,但你需要正确地获取和释放它们。