java变量本身是否安全? 更新变量时?

假设我有两个线程更新一个对象,一个线程从该对象读取而没有同步。 显然,这是运行条件。 但是,我想知道变量本身是否只能部分写入。

public class CommonObject extends Object { static int memberVar=-1; } public class Input1Thread extends Thread { public void run() { while(true) CommonObject.memberVar = 1 } } public class Input2Thread extends Thread { public void run() { while(true) CommonObject.memberVar = 2; } } public class OutputThread extends Thread { public void run() { while(true) System.out.println("CommonObject.memberVar"+ CommonObject.memberVar); } } 

我会假设打印出的值也将是2或1.但是,我想知道变量是否可能设置为中途?

我使用了原语作为一个例子,但是如果不同的话,我也希望对象的答案也是如此。

这取决于变量的类型。

如果它们volatile ,则允许double s和long s(Java中的两个64位类型)进行单词撕裂,而所有其他类型(包括引用)可能永远不会撕裂。 单词撕裂会给你你担心的行为:一些字节来自旧值,其中一些来自新值,整体结果是一个既不旧又不新的值。

这在JLS 17.7中指定:

出于Java编程语言存储器模型的目的,对非易失性long或double值的单次写入被视为两个单独的写入:每个32位一半写入一次。 这可能导致线程从一次写入看到64位值的前32位,而从另一次写入看到第二次32位的情况。

volatile和long值的写入和读取始终是primefaces的。

对引用的写入和读取始终是primefaces的,无论它们是作为32位还是64位实现。

当然,引入数据竞赛会带来许多问题; 但是你的问题专门针对单词撕裂,所以我只是在这里解决,除非要注意“只是因为你可以,并不意味着你应该”。 你应该小心分析你拥有的每个数据竞争并certificate它是良性的(因为它们中的一些 – 就像String.hashCode对其值的缓存一样)。

查看AtomicInteger类和线程上的java教程以获取示例。 还有javadoc。

https://docs.oracle.com/javase/tutorial/essential/concurrency/

它对于原语是安全的,但对于Object不安全。例如,对象A有两个变量int a,b,如果你试图在两个不同的线程中改变它们的值,你会发现两个线程的值有时可能同时出现。