【发布时间】:2012-03-19 19:56:52
【问题描述】:
假设您有 2 个或更多线程共享一个对象 A。
对象 A 内部有一个列表,其中包含另一个对象 B
对象 A 列表 对象B
现在线程修改/读取对象 B
问题是,应该同步什么? 对象 A,因为他们都访问它,或者对象 B,因为这是他们读取/修改的内容
我似乎无法在任何地方找到我的问题的答案。
提前致谢
【问题讨论】:
标签: java concurrency synchronized
假设您有 2 个或更多线程共享一个对象 A。
对象 A 内部有一个列表,其中包含另一个对象 B
对象 A 列表 对象B
现在线程修改/读取对象 B
问题是,应该同步什么? 对象 A,因为他们都访问它,或者对象 B,因为这是他们读取/修改的内容
我似乎无法在任何地方找到我的问题的答案。
提前致谢
【问题讨论】:
标签: java concurrency synchronized
走一条最简单、最安全的路线,您需要在对象层次结构中最外层的对象上进行同步,该对象应以原子方式操作。
在您的示例中,您似乎需要在 一个列表 上进行同步(不幸的是,如果没有实际代码,我无法确定您到底要做什么)。
这里是示例代码:
class B {
}
class A {
private final List<B> listOfBs = new ArrayList<B>();
void add(B b) {
synchronized (listOfBs) {
listOfBs.add(b);
}
}
List<B> getSnapshot() {
List<B> copy = new ArrayList<B>();
synchronized (listOfBs) {
copy.addAll(listOfBs);
}
return copy;
}
}
请注意,您需要将列表声明为final,以消除某些代码可能会更改对违反原子性的列表的引用:
// will make add() and getSnapshot() not mutually exclusive, thus violating atomicity of operations
...
listOfBs = new ArrayList<B>();
...
阅读Java concurrent programming tutorial 会有所帮助。
【讨论】:
getSnapshot() 中只有copy.addAll(listOfBs); 需要在同步块中。最好限制同步的范围。
如果您通过对象 B 的一种方法修改对象 B,那么您应该使该方法(或执行写入的部分)同步。
【讨论】: