在以下代码中:
class A {
private int number;
public void a() {
number = 5;
}
public void b() {
while(number == 0) {
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果调用方法b然后启动一个触发方法a的新线程,则方法b不能保证看到更改,number因此b可能永远不会终止.
当然,我们可以number volatile解决这个问题.但是出于学术原因,我们假设这volatile不是一个选择:
该JSR-133的常见问题告诉我们:
在我们退出synchronized块之后,我们释放了监视器,它具有将缓存刷新到主内存的效果,因此该线程所做的写操作对其他线程是可见的.在我们进入同步块之前,我们获取监视器,它具有使本地处理器高速缓存无效的效果,以便从主存储器重新加载变量.
这听起来像我只需要两个a并b进入和退出任何synchronized-Block,无论他们使用什么显示器.更确切地说,它听起来像这样......:
class A {
private int number;
public void a() {
number = 5;
synchronized(new Object()) {}
}
public void b() {
while(number == 0) {
// …Run Code Online (Sandbox Code Playgroud) 假设我有一个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的线程读取用户字段时,它是否看到处于新鲜状态的用户?如何以适当的线程安全方式做到这一点?
请注意,我无法修改用户类,我不知道它本身是否是线程安全的.