代码之家  ›  专栏  ›  技术社区  ›  Gandalf

锁定缓存密钥而不锁定整个缓存

  •  1
  • Gandalf  · 技术社区  · 16 年前

    Retrieving User [Bob]
    Retrieving User [Bob]
    Retrieving User [Bob]
    Returned [Bob] ...caching
    Returned [Bob] ...caching
    Returned [Bob] ...caching 
    

    我想要的是,第一个请求将调用用户服务,而其他两个请求将被阻止—当第一个请求返回,然后缓存对象时,其他两个请求将通过:

    Retrieving User [Bob]
    blocking...
    blocking...
    Returned [Bob] ...caching
    [Bob] found in cache
    [Bob] found in cache
    

    我考虑过锁定字符串“Bob”(因为由于实习,它总是同一个对象对吧?)。这样行吗?如果是这样的话,我该如何跟踪缓存中实际存在的密钥,并围绕它们构建一个锁定机制,一旦检索到有效对象,该机制就会返回有效对象。谢谢。

    3 回复  |  直到 16 年前
        1
  •  4
  •   erickson    16 年前

    String 在全球可见,所以他们是一个差劲的候选人。

    ConcurrentMap 并行映射

    ReadWriteLock trial = new ReentrantReadWriteLock(fair);
    ReadWriteLock lock = locks.putIfAbsent(key, trial);
    if (lock == null) {
      /* The current thread won the race to create lock for key. */
      lock = trial;
    }
    

    (使用 ReadWriteLock 是可选的;有了它,您可以做一些花哨的事情,比如允许多个线程同时读取缓存的值,但是当值需要更新时,仍然让另一个线程获得独占锁。)

    java.util.concurrent . 在这种情况下,您可以在地图上同步:

    Object lock;
    synchronized (locks) {
      if (locks.containsKey(key))
        lock = locks.get(key);
      else {
        lock = new Object();
        locks.put(key, object);
      }
    }
    
        2
  •  2
  •   Community Mohan Dere    9 年前

    我考虑过锁定字符串“Bob”(因为由于实习,它总是同一个对象对吧?)。这样行吗?

    I've previously tried this and it actually doesn't work quite like you might expect . 你一定要打电话 intern()

        3
  •  0
  •   CDSO1    16 年前

    如果您正在使用地图进行缓存,那么锁定该键将执行您的建议。