Does the unmodifiable wrapper for java collections make them thread safe?我需要使ArrayLists线程的ArrayList安全。 我也不能让客户对集合进行更改。 不可修改的包装器会使其线程安全吗,或者我需要在集合上使用两个包装器? 这取决于。包装器只会阻止对其包装的集合进行更改,而不是对集合中的对象进行更改。如果您有一个ArrayLists的ArrayList,则全局列表及其每个元素列表都需要单独包装,并且您可能还需要为这些列表的内容做些事情。最后,您必须确保原始列表对象没有更改,因为包装器仅阻止通过包装器引用而不是原始对象的更改。 在这种情况下,您不需要同步包装器。
关于一个相关主题-我已经看到了几条建议使用同步集合以实现线程安全的回复。
不可修改的包装器仅阻止更改其适用的列表的结构。如果此列表包含其他列表,并且您有尝试修改这些嵌套列表的线程,那么您将无法避免发生并行修改风险。 如果安全地发布了不可修改的视图,并且发布了不可修改的视图之后,则永远都不会修改可修改的原始文档(包括集合中递归包含的所有对象!),它将是线程安全的。 如果您想继续修改原始图,则可以创建集合对象图的防御性副本并返回该图的不可修改视图,或者使用固有的线程安全列表作为开头,然后返回该图的不可修改视图。 那。 如果您以后仍然打算不同步地访问List,则不能返回unmodifiableList(synchonizedList(theList))。 如果在多个线程之间共享可变状态,则所有线程在访问该状态时必须在相同的锁上进行同步。 根据定义,不可变对象是线程安全的(假设没有人保留对原始集合的引用),因此不需要同步。
使用Collections.unmodifiableList()包装外部ArrayList
也使用Collections.unmodifiableList()包装内部ArrayList
让我们知道此解决方案是否会引起问题(开销,内存使用情况等); 编辑:当然,如果列表被修改,它们不是线程安全的。我假设没有进一步的编辑。 我相信,因为UnmodifiableList包装器将ArrayList存储到最终字段,所以只要创建包装器后未修改列表,包装器上的任何读取方法都将看到构造包装器时的列表,并且只要包装器内部的可变ArrayList不被修改(包装器无法防范)。 通过查看"集合"源,看起来"不可修改"不会使其同步。
同步类包装器中有一个互斥对象来完成同步部分,因此看起来您需要同时使用两者。还是自己滚! 不知道我是否理解您要做什么,但我会说大多数情况下的答案是"否"。 如果将ArrayList和ArrayList设置为ArrayList和ArrayList,则在创建后就永远不能更改外部列表和内部列表(并且在创建过程中,只有一个线程可以访问内部列表和外部列表),它们可能被包装器线程安全(如果同时,外部列表和内部列表以无法修改的方式包装)。 ArrayList上的所有只读操作很可能是线程安全的。但是,Sun不能保证它们是线程安全的(也不适用于只读操作),因此,即使它可能现在就可以工作,但将来可能会中断(如果Sun创建了一些内部数据缓存来更快地访问它们)。例)。 在以下情况下这是必需的: 如果仅打算按索引从ArrayList中读取,则可以假定这是线程安全的。 如有疑问,请选择同步包装器。 |