Beh*_*nil 5 java multithreading thread-safety
假设我有一个JavaBean 用户,它从另一个线程更新,如下所示:
public class A {
private final User user;
public A(User user) {
this.user = user;
}
public void aMethod() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
...a long running task..
user.setSomething(something);
}
});
t.start();
t.join();
}
public void anotherMethod() {
GUIHandler.showOnGuiSomehow(user);
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码线程安全吗?我的意思是,当创建A实例并调用A.aMethod的线程读取用户字段时,它是否看到处于新鲜状态的用户?如何以适当的线程安全方式做到这一点?
请注意,我无法修改用户类,我不知道它本身是否是线程安全的.
这段代码线程安全吗?...它是否看到用户处于新鲜状态?
user并不是特别重要——代码中的final这一事实对线程安全几乎没有什么影响,除了它无法被替换这一事实之外。
应该更改的位是由 设置的实例变量setSomething。它应该被标记为volatile.
class User {
// Marked `volatile` to ensure all writes are visible to other threads.
volatile String something;
public void setSomething(String something) {
this.something = something;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果(如您所建议的)您无权访问该类User,则必须执行创建内存屏障的同步。在最简单的形式中,您可以使用user一个访问来包围您对 的synchronized访问。
synchronized (user) {
user.setSomething(something);
}
Run Code Online (Sandbox Code Playgroud)
添加:-事实证明(请参阅此处)实际上可以这样完成:
volatile int barrier = 0;
...
user.setSomething(something);
// Forces **all** cached variable to be flushed.
barrier += 1;
Run Code Online (Sandbox Code Playgroud)