1

我有这样的课。

public class Cache
{
    private static final ConcurrentHashMap<String, Cache> 
        CACHE = new ConcurrentHashMap<String, Cache>();

    ConcurrentHashMap<Long,ClassA> mapA = 
        new ConcurrentHashMap<String,ClassA>();

    ConcurrentHashMap<Long,Date> mapB = 
         new ConcurrentHashMap<Long,Date>();

}

类中还有其他几种方法可以从两个映射中添加、删除键。当一个线程更新 map A 时,另一个线程可以为同一个 Cache 实例更新 mapB。我还需要定期将此缓存保存到磁盘。保存时是否需要 ReadWriteLocks 来保持数据的完整性?

4

3 回答 3

1

据我所知,ConcurrentHashMaps 在内部是线程安全的,因此您不需要任何对象锁。并发哈希映射

支持检索的完全并发和可调整的预期更新并发的哈希表。此类遵循与 Hashtable 相同的功能规范,并包含与 Hashtable 的每个方法对应的方法版本。但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。

于 2013-10-27T02:45:12.683 回答
0

ConcurrentHashMap 的 writeObject 会在序列化之前锁定每个段,因此您无需担心数据完整性。注意:段之间可能存在间隙(在对象被序列化时更新非锁定段)。如果您想在 writeObject 期间完全锁定,请使用 Collections.synchronizedMap()。

参考方法 ConcurrentHashMap.writeObject():

private void writeObject(java.io.ObjectOutputStream s) throws IOException {
        // force all segments for serialization compatibility
        for (int k = 0; k < segments.length; ++k)
            ensureSegment(k);
        s.defaultWriteObject();

        final Segment<K,V>[] segments = this.segments;
        for (int k = 0; k < segments.length; ++k) {
            Segment<K,V> seg = segmentAt(segments, k);
            seg.lock();
            try {
                HashEntry<K,V>[] tab = seg.table;
                for (int i = 0; i < tab.length; ++i) {
                    HashEntry<K,V> e;
                    for (e = entryAt(tab, i); e != null; e = e.next) {
                        s.writeObject(e.key);
                        s.writeObject(e.value);
                    }
                }
            } finally {
                seg.unlock();
            }
        }
        s.writeObject(null);
        s.writeObject(null);
    }
于 2013-11-03T10:53:11.663 回答
0

这取决于应用程序逻辑。例如,您可以安全地遍历映射的条目并将它们保存到文件中,而其他线程正在更改映射。但这不是原子操作。如果您想要一致的快照,则需要同步。

于 2013-10-27T03:08:06.247 回答