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的

为什么这个java类不是线程安全的

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也是这样吗?