寻找合适的同步机制

时间:2019-06-01 17:09:53

标签: java concurrency java.util.concurrent mutual-exclusion

假设我有以下(伪)代码:

class Cache {
    Entry addIfMissing(String data) {
        // omitted for brevity
    }
    void evictOldEntries() {
        // omitted for brevity
    }
}
class Program {
    private Cache cache = new Cache();

    doWork() { // called from multiple threads
        var entry = cache.addIfMissing("omitted for brevity");
        // work with entry
    }

    static {
        Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
            cache.evictOldEntries();
        }, 10, 10, TimeUnit.MINUTES);
    }
}

我想确保evictOldEntries方法正在运行时,程序中的所有其他线程都必须等待它完成。

在这种情况下哪种同步机制合适?

3 个答案:

答案 0 :(得分:3)

您需要的是这样的

class Cache {

    ReentrantLock lock;

    public Cache { lock = new ReentrantLock(); }

    Entry addIfMissing(String data) {
        if (lock.isLocked) lock.wait();
        // Add data here
    }

    void evictOldEntries() {
        if (lock.tryLock()) {
           try {
              // Evict old entries
           }
           finally {
              lock.unlock();
              lock.notify();
           }
        }
    }
}

答案 1 :(得分:1)

在这里请稍加自由,因为您的代码示例和确切要求尚不清楚。但是,这样的工作可能吗? ConcurrentHashMap使用细粒度锁定,因此可以在将条目插入高速缓存时最大程度地减少瓶颈。退出线程甚至可以与插入线程同时运行。

class Cache<String, CacheEntry> {
    ConcurrentHashMap<String, CacheEntry> map = new ConcurrentHashMap<String, CacheEntry>();

    Entry addIfMissing(String data) {
        map.computeIfAbsent(...);
    }

    void evictOldEntries() {
        Iterator<Map.Entry<String, CacheEntry>> iterator = map.entrySet().iterator();

        while (iterator.hasNext()) {
            CacheEntry entry = iterator.next().getValue();

            if (shouldEvict(entry)) {
                iterator.remove();
            }
        }
    }
}

答案 2 :(得分:1)

我认为ReentrantReadWriteLock正是我所需要的:

[[1, 2]]
------
[[1]]

这样,一旦获得class Program { private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void doWork() { // called from multiple threads rwl.readLock().lock(); try { var entry = cache.addIfMissing("omitted for brevity"); // work with entry } finally { rwl.readLock().unlock(); } } static { Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { rwl.writeLock().lock(); try { cache.evictOldEntries(); } finally { rwl.writeLock().unlock(); } }, 10, 10, TimeUnit.MINUTES); } } 的writeLock,就必须阻止,反之亦然。