【问题标题】:Java multi-thread programming - atomic operationJava多线程编程——原子操作
【发布时间】:2013-01-02 03:31:54
【问题描述】:

我正在学习使用 Java 进行多线程编程。这是我的困惑。

class Cache<K, V> {
private ConcurrentMap<K, V> cache;
private ConcurrentLinkedQueue<K> lru;

public Cache () {
    // initiate cache and lru
}

public put (K key, V value) {
    // some pre-processing
    synchronized (this) {
        cache.put(key, value);
        lru.add(key);
    }
    // some post-processing
}

}

这是一些非常简单的缓存,其中包含最近最少使用的记录 (lru)。显然我需要使这两个操作原子化。否则很可能cache和lru的状态不同。

现在假设我想要一个定时任务来清理缓存,假设它会清理一半的缓存。我的问题是我上面的代码是否确保这两个操作(放置缓存和添加 lru)对于清理任务来说是原子的?我可以执行以下操作吗:

class CleanTask {
    Cache cache;   // the reference of Cache
    public void run () {
        // some pre-processing
        for (int i = 0; i < n; i++) {   // Just suppose I need remove n element
            synchronized (XXX) {
                cache.getCache().remove(cache.getLru().poll());
            }
        }
    }
}

我应该在 XXX 中输入什么?

非常感谢!!!

【问题讨论】:

  • 你的 LRU 不应该是班级公共合同的一部分。而且您的 clean 方法应该可能由缓存本身实现,而不是由外部任务实现。
  • 除非您将其作为学习练习来实现,否则您可能想看看 Google Guava code.google.com/p/guava-libraries/wiki/CachesExplained 中的缓存包 - 即使这是一个学习练习,也可能值得了解如何无论如何,番石榴的人都已经实现了。
  • @Perception 您所说的“LRU 不应该成为班级公共合同的一部分”是什么意思?我的想法是,当缓存达到其容量时,它会启动一个线程来完成清理工作,但同时,用户应该仍然能够将东西放入缓存中。
  • @msandiford 谢谢!我正在尝试向 Guava 学习。

标签: java multithreading concurrent-programming


【解决方案1】:

我的问题是我上面的代码是否确保这两个操作(放置缓存和添加 lru)对于清理任务来说是原子的?

是(假设清理任务在不同的线程中)

我应该在 XXX 中输入什么?

同一个缓存对象例如:synchronized (cache) { a 同步应该发生在同一个锁(对象)上

如果它们对您的情况有用,您还可以探索 Java 中的其他原子类:atomic package

【讨论】:

【解决方案2】:

在您的情况下,您将在 XXX 的 cache 上同步,但是,我建议您将 putgetLru 方法同步为另一种选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多