Caching all the prepared statements in thread safe way I have a below Singleton class where in my getStatement method, I populate a CHM by doing if check.

public class CacheHolder {
  private static final Map&lt;String, PreparedStatement&gt; holder = new ConcurrentHashMap&lt;&gt;();

  private static class Holder {
    private static final CacheHolder INSTANCE = new CacheHolder();
  }

  public static CacheHolder getInstance() {
    return Holder.INSTANCE;
  }

  private CacheHolder() {}

  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();
  }
}


I am working with Cassandra and using datastax java driver so I have to re-use prepared statements and that's why I am caching it here. Prepared Statement and BoundStatement.

Is there any better way of making my getStatement method thread safe instead of using synchronized block like that? Any other data structure which might be thread safe for these kind of operations?

I am working with Java 7.
public BoundStatement getStatement(String cql) {
    Session session = TestUtils.getInstance().getSession();
    PreparedStatement ps = holder.computeIfAbsent(cql, s -&gt; session.prepare(s));
    return ps.bind();
}


According to computeIfAbsent's Javadoc:


  The entire method invocation is performed atomically, so the function is applied at most once per key.


I also suggest that you declare holder of type ConcurrentHashMap instead of Map so that it becomes unambiguous for anyone reading getStatement that the synchronisation in computeIfAbsent is guaranteed.