为了账号安全,请及时绑定邮箱和手机立即绑定

寻找合适的同步机制

寻找合适的同步机制

白板的微信 2022-12-28 16:49:09
假设我有以下(伪)代码: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 回答

?
侃侃无极

TA贡献2051条经验 获得超10个赞

你需要的是这样的:


class Cache {


    final ReentrantLock lock;


    public Cache { lock = new ReentrantLock(); }


    Entry addIfMissing(String data) {

        lock.lock();

        try {

            // Add data here

        }

        finally {

            lock.unlock();

        }

    }


    void evictOldEntries() {

        if (lock.tryLock()) {

           try {

              // Evict old entries

           }

           finally {

              lock.unlock();

           }

        }

    }

}


查看完整回答
反对 回复 2022-12-28
?
阿晨1998

TA贡献2037条经验 获得超6个赞

由于您的代码示例和确切要求有点不清楚,因此在这里有点自由。但是这样的事情可能行得通吗?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();

            }

        }

    }

}


查看完整回答
反对 回复 2022-12-28
?
蓝山帝景

TA贡献1843条经验 获得超7个赞

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

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 就doWork必须阻塞,反之亦然。


查看完整回答
反对 回复 2022-12-28
  • 3 回答
  • 0 关注
  • 81 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信