4

我有一个在线程 A 中运行的控制器类,并像这样组成一个局部变量列表

线程 A

list = new ArrayList<Map<String, Order>>();
list.add(...);
list.add(...);

其中 Order 是一个 Java bean,它有几个原始属性,如 String、int、long 等。

一旦构造了这个列表,它的引用就会被传递给 Activity 的 UI 线程(线程 B)并在那里访问。跨线程通信是使用 Handler 类 + post() 方法完成的。

所以问题是,我可以完全不同步地从线程 B 访问列表数据吗?请注意,在线程 A 中构建后,列表将根本不会被访问/修改。它就像一个局部变量一样存在,然后被传递给线程 B。

4

4 回答 4

2

这是安全的。在消息队列中完成的同步建立了先发生关系。这当然假设您之后也不修改地图。此外,地图中包含的任何对象等都不得在没有适当同步的情况下被其他线程修改。

简而言之,如果列表和其中的任何数据都没有被 B 以外的其他线程修改,则不需要任何进一步的同步。

于 2013-07-25T15:30:53.007 回答
1

从您提供的上下文中不清楚这种情况发生在哪里:

list = new ArrayList<Map<String, Order>>();
list.add(...);
list.add(...);

如果它在构造函数中并且 listfinal 并且this引用没有从构造函数中泄漏,并且绝对确定它list不会改变(例如通过使用unmodifiableList装饰器方法)并且Order实例的引用不能从其他地方访问而不是它可能可以不使用同步。否则你的头上就有达摩克利斯之剑。

我提到了这些Order参考资料,因为如果您从其他地方更改它们,您可能不会遇到异常,但这可能会导致数据不一致/损坏。

于 2013-07-25T15:29:34.683 回答
0

如果您可以保证列表不会被修改,那么您不需要同步,因为所有线程将始终看到相同的列表。

于 2013-07-25T15:16:15.767 回答
-3

是的,如果您只是要读取数据,则无需同步。

请注意,即使线程 A 最终会在线程 B(或任何其他数量的线程)正在访问它时修改列表,您仍然不必同步,因为在任何给定时间只有一个写入器。

对不起,上述说法并不完全正确。如JavaDoc中所述:

如果多个线程同时访问一个 ArrayList 实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步。(结构修改是添加或删除一个或多个元素,或显式调整后备数组大小的任何操作;仅设置元素的值不是结构修改。)

另请注意,我没有考虑元素修改,而是纯粹的列表修改。

于 2013-07-25T15:12:02.600 回答