如何使用 get 和 put 作为原子操作使并发哈希映射线程安全?
How to make concurrent hash map thread safe with get and put as an atomic operation?
我下面的方法线程安全吗?此方法在 Singleton class.
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();
}
我正在使用 Cassandra 并使用 datastax java 驱动程序,所以我正在重用准备好的语句,这就是我将它缓存在这里的原因。 Prepared Statement and BoundStatement.
有没有更好的方法使我的 getStatement
方法线程安全(如果它是线程安全的)而不是像那样使用同步块?任何其他可能对此类操作线程安全的数据结构?我正在与 Java 7.
合作
因为.putIfAbsent在Java7中,你可以使用它:
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();
}
请注意,putIfAbsent 仍然在内部使用相同的同步。
如果你想做某种形式的记忆,那么这就是你可以在 Java 中做的 best/easiest 7. Guava 有一个你可以使用的计算缓存实现 Java 8 在 Map
接口中有一个 computeIfAbsent
方法,但你显然在这里不走运。
如果您可以像 Alexey 的回答所建议的那样在空竞赛中创建对象,那将是最好的解决方案。如果不能,那么您的实现既线程安全又合理。
这是一种双重检查锁定的形式,但是,通过使用此实现,您可以使用 CHM 的 put
和 get
方法确保先发生排序。
我下面的方法线程安全吗?此方法在 Singleton class.
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();
}
我正在使用 Cassandra 并使用 datastax java 驱动程序,所以我正在重用准备好的语句,这就是我将它缓存在这里的原因。 Prepared Statement and BoundStatement.
有没有更好的方法使我的 getStatement
方法线程安全(如果它是线程安全的)而不是像那样使用同步块?任何其他可能对此类操作线程安全的数据结构?我正在与 Java 7.
因为.putIfAbsent在Java7中,你可以使用它:
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();
}
请注意,putIfAbsent 仍然在内部使用相同的同步。
如果你想做某种形式的记忆,那么这就是你可以在 Java 中做的 best/easiest 7. Guava 有一个你可以使用的计算缓存实现 Java 8 在 Map
接口中有一个 computeIfAbsent
方法,但你显然在这里不走运。
如果您可以像 Alexey 的回答所建议的那样在空竞赛中创建对象,那将是最好的解决方案。如果不能,那么您的实现既线程安全又合理。
这是一种双重检查锁定的形式,但是,通过使用此实现,您可以使用 CHM 的 put
和 get
方法确保先发生排序。