下面的方法线程安全吗?此方法在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();
}我正在使用Cassandra并使用datastax驱动程序,所以我重用准备好的语句,这就是我在这里缓存它的原因。准备陈述和BoundStatement.
有什么更好的方法来使我的getStatement方法线程安全(如果它是线程安全的话),而不是像这样使用同步块?对于这类操作,是否还有线程安全的其他数据结构?我正在使用Java 7。
发布于 2016-11-27 17:56:05
由于.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在内部仍然使用相同的同步。
发布于 2016-11-28 12:05:13
如果您想做某种形式的回忆录,那么这是您在Java 7中能够做的最好/最简单的方法。番石榴有一个可以使用的计算缓存实现,而Java 8在Map接口中有一个Map方法,但显然您在这里运气不佳。
如果你能在一个空的竞赛中创建对象,就像Alexey的答案所建议的那样,这将是最好的解决方案。如果不能,您的实现是线程安全和合理的。
这是一种双重检查锁定的形式,但是,在使用CHM的put和get方法进行排序之前,您将确保发生这种情况。
https://stackoverflow.com/questions/40831817
复制相似问题