考虑两个线程: threadA 和 threadB 。 (例如,让 threadA 成为UI线程,让 threadB 成为Thread
的子类。)关于数据可见性,是吗?安全地在 threadA 中实例化一个类,将它传递给 threadB 的构造函数,然后从 threadB 中专门使用它?让我用代码澄清一下。 (请注意,代码已经过简化,因此这种架构在实际应用中以其实际形式有意义。)
public class SomeClass {
public SomeClass(....) {
// initialization
}
}
public class MyCustomThread extends Thread {
public MyCustomThread(SomeClass someClass) {
mSomeClass = someClass;
}
@Override
public void run() {
// operate on mSomeClass
}
}
启动所有内容的方法如下(其位置无关紧要)。这由 threadA 调用。
public void launchThread() {
SomeClass someClass = new SomeClass();
MyCustomThread threadB = new MyCustomThread(someClass); // MyCustomThread is a subclass of Thread
threadB.start();
// After this point, threadA never accesses someClass,
// and only threadB is operating on it
}
我知道不允许构造函数同步,并且内部不需要同步代码(因为 this 引用 - 除非泄露 - 在该类之前不可用于其他线程是在其创建者线程中构建的)。所以我的问题是关于数据可见性:代码是安全的,前提是我在调用someClass
后不从 threadA 访问threadB.start()
(及其任何引用的数据)?
换句话说,threadB.run()
会查看最新版本的someClass
数据(例如字段,内部参考资料等)吗?我猜:由于 threadB 首次访问someClass
后someClass
上没有外部更改, threadB 必须看到正确的值,因为它不能拥有之前的缓存副本。因此,出于上述原因,我无需在someClass
的同步块中访问threadB.run()
。 (同样,请注意, threadB 启动后, threadA 无法访问someClass
。
答案 0 :(得分:2)
如果您这样说,在threadB.start()
之后,someClass
引用的实例将不再被任何其他线程修改:是的,threadB.run()
将看到最新版本。
在这种情况下,确实没有并发/竞争条件。一切都按顺序发生,你只需要Thread
s的对象,我认为这可能会让你有点偏执:)。