为什么这个Java类不是线程安全的。
class TestClass {
private int x;
int get() {
return x;
}
void set(int x) {
this.x = x;
}
}
我读到了关键字synchronized
是用来使代码线程安全的?毕竟操作不是在原子级别执行吗?
为什么这个Java类不是线程安全的。
class TestClass {
private int x;
int get() {
return x;
}
void set(int x) {
this.x = x;
}
}
我读到了关键字synchronized
是用来使代码线程安全的?毕竟操作不是在原子级别执行吗?
尽管赋值本身是原子操作,但由于不同的硬件和编译器实现,不同的线程可能会看到成员变量x的不同值。也就是说,一个线程的修改对另一个线程来说可能是不可见的,因为有一些缓存机制。这通常被称为线程可见性问题。
您可以通过在监视器上同步(使用synchronized关键字或java.util.concurrent锁)或将x声明为volatile来适当地同步代码。
在多处理器系统中,某些值可能会被处理器缓存,并且可能不反映其他线程/处理器对相同对象所做的更改。实际上,即使只有一个处理器,JVM也可以实现这种工作方式。
语言规范明确要求同步方法呈现内存屏障,并要求从内存重新读取所有实例变量。
因为您的代码未同步,因此一个线程可能会设置该值,但另一个线程将返回仍由该线程缓存的值。
请阅读Java语言规范的'Memory and Locks'章节。
当你有两个方法修改/访问一个非易失性变量时,它永远不是线程安全的。如果你想只有一个方法,你可以尝试:
synchronized int getAndSet(int x, boolean set) {
if (set) this.x = x;
return this.x; // param x is for set
}