最终字段的线程安全 [英] Thread safety of final field
问题描述
假设我有一个JavaBean User ,它是从另一个线程更新的,例如:
Let's say I have a JavaBean User that's updated from another thread like this:
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);
}
}
此代码线程安全吗?我的意思是,当创建A实例并称为A.aMethod的线程读取用户字段时,它是否看到用户处于全新状态?如何以适当的线程安全方式进行操作?
Is this code thread safe? I mean, when the thread that created A instance and called A.aMethod reads user fields, does it see user in the fresh state? How to do it in appropriate thread safe manner?
请注意,我无法修改用户类,也不知道它本身是否是线程安全的.
Note that I can't modify the user class and I don't know if it's thread safe itself.
推荐答案
此代码线程安全吗? ...它看到用户处于全新状态吗?
Is this code thread safe? ... does it see user in the fresh state?
并不是特别的-user
在代码中是最终的,除了不能替换外,对线程安全几乎没有任何影响.
Not especially - the fact that user
is final in your code makes almost no difference to thread safety other than the fact that it cannot be replaced.
应更改的位是setSomething
设置的实例变量.它应该标记为volatile
.
The bit that should change is the instance variable that is set by setSomething
. It should be marked as 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;
}
}
但是,如果(如您建议的那样)您没有访问User
类的权限,则必须执行创建内存障碍的同步.以其最简单的形式,您可以使用synchronized
访问权限来包围对user
的访问.
If however (as you suggest) you do not have access to the User
class, you must then perform a synchronization that creates a memory barrier. In its simplest form you could surround your access to the user
with a synchronized
access.
synchronized (user) {
user.setSomething(something);
}
添加了:-事实证明(请参见此处),实际上可以这样做:
Added :- It turns out (see here) that this can actually be done like this:
volatile int barrier = 0;
...
user.setSomething(something);
// Forces **all** cached variable to be flushed.
barrier += 1;
这篇关于最终字段的线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!