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

线程安全对象池,如果存在强引用,保证返回现有对象?

  •  3
  • jennykwan  · 技术社区  · 15 年前

    我试图扩展Clojure语言,将ACI保证的refs扩展到ACID保证的drefs(持久的refs)。API只是简单地调用 (dref key value) key 是要在基础数据存储中使用的密钥字符串(在我当前的实现中是BDB-JE),并且 value 钥匙 已存在于数据库中,则使用存储的值。

    可以使用同一个键创建多个dref,它们需要同步,即,如果一个键为“A”的dref参与了一个事务,而该事务是用一个键写入或读取的 (ensure)

    出于显而易见的原因,简单地确保这个逻辑dref是用一个具体的内存dref实现的要容易得多。这样就没有什么可同步的了。我该怎么做?

    显而易见的答案是使用一个键控的对象池 . 然后Clojure将调用静态 getInstance(key,value) 方法从池中检索(如果存在),并创建它并填充池(如果不存在)。这种方法的问题是没有简单的方法让Clojure 完成后的对象。内存泄漏城市。我必须确保对它有强引用的任何对象都不会被收集,并且它们存在于池中。如果池丢失对仍在使用的逻辑dref的引用,这将是灾难性的,因为另一个进程可能会使用相同的密钥创建一个新的dref,而使用另一个具有相同密钥的dref在事务上是不安全的。

    WeakHashMap SoftReference 代表GC的不情愿)。所以:

    1. HashMap<String,SoftReference<DRef>> ,如果收集了条目(SoftReference)的值,如何确保映射将逐出条目?某种守护进程线程?
    2. 如何使池线程对GC安全?或者我不必担心,因为GC是在 软引用 Map 水平?
    3. 另一方面,如何确保守护进程线程正在运行?有没有什么方法可以让它停止而不抛出一个异常,这个异常如果未触发的话会使整个JVM崩溃?如果是这样,我如何监控并在需要时启动一个新的?
    3 回复  |  直到 15 年前
        1
  •  1
  •   Nicolas Oury    15 年前

    你试过谷歌收藏吗?

    它们有一个MapMaker,它提供了各种带有软键/弱键和值的并发哈希映射。 一个问题是,弱/软键的等式是identity,这很烦人,但如果键是字符串,可能不会太多。

        2
  •  1
  •   Alex Miller    15 年前

    pssst….你正在重建Terracotta的分布式共享对象。Terracotta的内部看起来与此非常相似,尽管它们(在DSO中)依赖于在加载时使用字节码操作来截获对字段的所有读写,而在Clojure中则要简单得多。

    如果您想查看Terracotta实现,那么ClientObjectManager( http://svn.terracotta.org/svn/tc/dso/trunk/code/base/dso-l1/src/com/tc/object/ )是管理共享对象的主客户端类。查看pojoToManaged并查看TCObjectImpl中的一些相关代码。

    The Ghost in the Virtual Machine

    3) 谷歌搜索未捕获的异常处理程序。。。

        3
  •  0
  •   Sbodd    15 年前

    简单的答案可能只是 Collections.SynchronizedMap(new WeakHashMap()) -尽管这本身并不能提供线程安全的迭代。

    Map<K, V> 你自己,并授权给 ConcurrentHashMap<K, SoftReference<V> > . 你可以把你的 SoftReferences 在一个 ReferenceQueue ,并使用守护进程线程从映射中删除引用,或者只检查 引用队列

    3) 您可以看看AWT EventQueue是如何管理的。但是:

    -守护进程线程可能足够简单,不会抛出意外的异常

    -如果你关心它,你可以把守护进程线程的肉包起来

    for (;;) {
      try {
        //daemon thread loop here
      } catch (Exception ex) {
        //log it, any other possible cleanup
      }
    }