Java类中的线程安全
为什么这个java类不是线程安全的Java类中的线程安全,java,thread-safety,Java,Thread Safety,为什么这个java类不是线程安全的 class TestClass { private int x; int get() { return x; } void set(int x) { this.x = x; } } 我读到需要关键字synchronized才能保证线程安全?毕竟操作不是在atomic内部完成的吗?对于多个处理器,一些值可能会被处理器缓存,并且可能不会反映其他线程/处理器对相同对象所做的更改。实际上,JVM的
class TestClass {
private int x;
int get() {
return x;
}
void set(int x) {
this.x = x;
}
}
我读到需要关键字
synchronized
才能保证线程安全?毕竟操作不是在atomic内部完成的吗?对于多个处理器,一些值可能会被处理器缓存,并且可能不会反映其他线程/处理器对相同对象所做的更改。实际上,JVM的实现方式可能是这样的,即使只有一个处理器
语言规范明确要求同步方法提供内存障碍,并要求从内存中重新读取所有实例变量
由于代码未同步,一个线程可以设置该值,但另一个线程将返回该线程仍缓存的值
请阅读Java语言规范的一章。因为字段“x”未声明为volatile,所以JVM不需要确保“x”对所有其他线程可见。也就是说,如果一个线程不断读取“x”的值,而另一个线程正在写入该值,则读取线程可能永远不会“看到”该值的变化
不需要同步关键字,但它会创建必要的内存屏障/缓存刷新,以确保“x”可见,但在这种情况下使用volatile关键字会更有效。尽管分配本身是一种原子操作,但由于硬件和编译器实现不同,不同的线程可能会看到成员x的不同值。也就是说,由于某种缓存,一个线程的修改可能对另一个线程不可见。这通常称为线程可见性问题
您可以通过在监视器上同步(使用synchronized关键字或java.util.concurrent锁)或将x声明为volatile来正确同步代码。当您有两种方法修改/访问非volatile变量时,它永远不会是线程安全的。如果您只想使用一种方法,可以尝试:
synchronized int getAndSet(int x, boolean set) {
if (set) this.x = x;
return this.x; // param x is for set
}
C#a也是这样吗?