Java TreeMap-同步文档说明

Java TreeMap-同步文档说明,java,javadoc,Java,Javadoc,TreemapJavadoc有下面的部分,我无法理解下面部分的最后一行。这是否意味着创建一个锁并将映射修改逻辑移动到一个同步块或其他所有东西中。只有结构修改需要同步,访问是线程安全的 请注意,此实现未同步。 如果多个线程同时访问一个映射,并且至少有一个线程在结构上修改了映射,那么它必须在外部同步。(结构修改是添加或删除一个或多个映射的任何操作;仅更改与现有键关联的值不是结构修改。)这通常通过在自然封装映射的某个对象上同步来完成。如果不存在此类对象,则应使用Collections.synchron

TreemapJavadoc有下面的部分,我无法理解下面部分的最后一行。这是否意味着创建一个锁并将映射修改逻辑移动到一个同步块或其他所有东西中。只有结构修改需要同步,访问是线程安全的

请注意,此实现未同步。

如果多个线程同时访问一个映射,并且至少有一个线程在结构上修改了映射,那么它必须在外部同步。(结构修改是添加或删除一个或多个映射的任何操作;仅更改与现有键关联的值不是结构修改。)
这通常通过在自然封装映射的某个对象上同步来完成。如果不存在此类对象,则应使用Collections.synchronizedSortedMap方法“包装”地图。

这是否意味着创建锁并移动地图修改逻辑 一个同步的块或其他东西。 只有结构修改需要同步和同步吗 访问是线程安全的

不,这还不够。
仅同步进行结构修改的处理是不够的,因为如果读取映射的方法未同步,则该方法可以与同步方法同时调用。
因此,对地图的访问可以与读取操作和结构修改操作同时进行。这是不可取的。


最后,这意味着,如果多个线程同时访问映射,并且至少有一个线程修改映射结构,那么所有对映射的访问都应该同步。

基本上,Javadoc相当混乱,因为如果您修改映射(包括仅更改与现有键关联的值时),您希望在几乎所有情况下同步所有操作。不需要同步的(几乎)唯一时间是,如果地图在发布后是完全只读的

现在,为什么Javadoc会说如果。。。至少有一个线程在结构上修改映射——这是因为如果您只是更改与现有密钥相关联的值,那么最糟糕的情况可能是您在一段未指定的时间内读取了过时的值。相反,如果在没有同步的情况下进行结构更改,则可能会发生更糟糕的事情(如
NullPointerException
s,无限循环)


然而,与允许过时的值相比,同步或使用并发集合几乎总是更好的

是的,是的,它会。@MikeNakis如果线程只操作内部的值,而不修改结构,那么在非同步映射中是否是线程安全的。更不用说,只“读取”数据结构的操作实际上可能会更改它们(例如散放树)。您不知道(也不需要知道)
get()
的实现在幕后会做什么。@biziclop感谢您的反馈。我发现执行地图修改的公共读取方法是一个糟糕的API。请在TreeMap或Java Collection中提供一个示例?正如我所说,这就是splay树真正的工作原理。您搜索的最后一个元素将移动到树的根,以加快后续对同一元素的查找。内置的
TreeMap
没有,但是实现在
get()
中更改其内部状态是完全合法的,只要它不影响从外部可见的任何内容。实际上,从概念上讲,对于splay树。我完全同意这样做是合法的,但我认为出于并发性考虑,应该指定方法的API。例如:同步一个经典的
HashMap
,该HashMap只在客户端访问一次时执行读取,这是一个代价高昂的权衡,应该避免。