如何在一个r/w线程和一个只读线程之间同步Map?

eri*_*oco 5 java multithreading map synchronized data-structures

我有一个Collections.synchronizedMap()由线程A读取和更新的同步Map(via ).线程B仅通过Map.keySet()(只读)访问Map .

我应该如何同步?该文件说,键集()(对于Collections.synchronizedMap)"不需要在synchronized块".我可以在同步块中放置线程A的读/写访问权限,但这是否必要?

我想即使使用同步Map或同步块,如果Map.keySet不需要同步(根据上面的文档链接),我似乎很奇怪...

更新:我错过了必须同步keySet的迭代,即使检索keySet不需要同步.拥有keySet而不能查看它并不是特别令人兴奋,因此最终结果=需要同步.改为使用ConcurrentHashMap.

Gra*_*ray 3

要制作真正的读/写与读/仅锁定Map包装器,您可以查看Collections使用的包装器synchronizedMap()并将所有synchronized语句替换为ReentrantReadWriteLock. 这是一项很好的工作。相反,您应该考虑改用 a 来ConcurrentHashMap完成所有正确的事情。

就 而言keySet(),它不需要位于一个synchronized块中,因为它已经synchronized位于Collections.synchronizedMap(). keySet()Javadocs只是指出,如果您正在迭代地图,则需要对其进行同步,因为您正在执行多个操作,但是当您获取包装在SynchronizedSet执行其操作的类中的类时,不需要同步自己的同步。

最后,您的问题似乎暗示如果您只是阅读某些内容,则不需要同步某些内容。您必须记住,同步不仅可以防止竞争条件,还可以确保每个处理器正确共享数据。即使您Map以只读方式访问 a,如果任何其他线程正在更新它,您仍然需要对其进行同步。