1

我想在ConcurrentHashMap. 对二进制文件的修改也应该反映在缓存中。由于缓存将被多个线程使用,所有 IO 操作都是同步的。地图的修改进入同synchronized一块内。大致如下:

synchronized (file) {
    file.deleteRecord(index)
    map.remove(index);
}

synchronized(file) {
    file.writeRecord(index, record);
    map.put(index, record);
}

两者mapfile都是私有的,从缓存类外部看不到。

map.get(index)如果缓存读取,即没有块,是否保留线程安全synchronized

正如我前面提到的,ConcurrentHashMap是用作地图实现的。

4

4 回答 4

5

是的。这基本上是重点ConcurrentHashMap。从文档中

检索操作(包括 get)一般不会阻塞,因此可能与更新操作(包括 put 和 remove)重叠。检索反映了最近完成的 更新操作在其开始时保持的结果。

并从包文档中:

并发集合是线程安全的,但不受单个排除锁的控制。在特定情况下ConcurrentHashMap,它安全地允许任意数量的并发读取以及可调数量的并发写入。

(当然,这两个文档页面都有更多详细信息。它们值得仔细阅读。)

于 2009-07-05T18:31:40.380 回答
2

是的,多亏了 ConcurrentHashMap 实现,线程安全被保留到映射引用。

您存储在地图中的对象是另一回事。

于 2009-07-05T18:33:21.080 回答
1

是的,ConcurrentHashMap 是线程安全的,因此读取(或写入)不需要您进行任何锁定。

但是,在您的示例中,您最终可能会遇到以下事件序列:

file.deleteRecord(index);
map.get(index) // returns the mapping for index even though it has been deleted from file
map.remove(index);

(对于 writeRecord/put 也是一样的)。在您的情况下,这可能是也可能不是问题。

于 2009-07-06T23:42:20.183 回答
0

好吧,正如这里的每个人所说,这是线程安全的,因为在写入缓存和从缓存读取之间存在先发生关系,但这可能毫无意义,具体取决于您希望获得的其他保证。

例如,除非您 fsync 文件,否则无法保证记录会写入磁盘,因此您可能不会从磁盘读取记录(取决于文件系统和其他一些因素)。在 writeRecord/deleteRecord 和映射写入和从映射读取之间也没有发生之前的关系,因此 JMM 不保证您从映射中读取肯定已写入文件的内容。

您确实可以保证写入的indexrecord对象的状态将是读取的状态,尽管如果其中任何一个是可变的,那么这可能是一个相当无用的保证。

于 2011-01-05T23:36:47.390 回答