为什么即使在不使用volatile的情况下,在一个线程中修改共享变量也会影响另一个线程? - java

这里有三个简单的类:

第1类:

public class ThreadSyncMain {

public static int count = 0; // volatile is not use

public static void main(String[] args) {

    Thread thread1 = new Thread( new Thread1(),"Thread1" ); 
    Thread thread2 = new Thread( new Thread2(),"Thread2");

    thread1.start();
    thread2.start();

}

}

第2类:

public class Thread1 implements Runnable{
public void run() {

    System.out.println("Thread1 Count :: "+ThreadSyncMain.count);
    ThreadSyncMain.count++;
}

}

第3类:

public class Thread2 implements Runnable{
public void run() {

        System.out.println("Thread2 Count :: "+ThreadSyncMain.count);

}
}

输出为:

线程1计数:: 0
线程2计数:: 1

这意味着线程1更改了计数值。那么为什么线程1中的更改​​会影响线程2,因为我没有使用任何“volatile”关键字。在这种情况下,“volatile”关键字不是问题吗?如何修改代码以测试“volatile”?

提前致谢。

更新部分:
经过一些命中和试用测试后,我正在更新代码。 1类保持不变。这是更新的代码:

第2类:我增加了100毫秒的延迟。

public class Thread1 implements Runnable{
public void run() {

    System.out.println("Thread1 Count :: "+ThreadSyncMain.count);

    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    ThreadSyncMain.count++;
}

}

第3类:添加了while循环。内部持续监控计数。

public class Thread2 implements Runnable{
public void run() {

    while(true)
    {
        if(ThreadSyncMain.count == 1)
        { 
            System.out.println("Thread2 Count :: "+ThreadSyncMain.count);
        }
    }

}
}

现在在这种情况下,我得到以下输出:
1.如果在class1中未使用“volatile”,则输出为:

 Thread1 Count :: 0

2.如果在class1中使用“volatile”,则输出为:

Thread1 Count :: 0
Thread2 Count :: 1
Thread2 Count :: 1
Thread2 Count :: 1
.
.
.

为什么在这种情况下会出现挥发物?

参考方案

每个线程都有一个内存视图。如果不使用锁,则不能保证这些视图在线程之间是一致的。这样,共享变量就可以了,因为您可以在线程中看到它,所以可以像上面一样共享一个变量(没有volatile),但是会给您不可靠的结果。使用volatile关键字意味着在线程之间始终读取变量。

参见here,特别注意:

Volatile 字段是用于通信的特殊字段
线程之间的状态。每次读取volatile将看到最后一次写入
通过任何线程来解决该问题;实际上,它们是由
程序员作为永远都无法看到“过时”的领域
缓存或重新排序的结果。

Java:正则表达式模式匹配器是否有大小限制? - java

我的模式类似于OR:“word1 | word2 | word3”我大约有800个字。可能有问题吗? 参考方案 您仅受记忆和理智的限制。 :)

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

Java-搜索字符串数组中的字符串 - java

在Java中,我们是否有任何方法可以发现特定字符串是字符串数组的一部分。我可以避免出现一个循环。例如String [] array = {"AA","BB","CC" }; string x = "BB" 我想要一个if (some condition to tell wheth…

Java:我可以在Hashmaps中使用数组吗? - java

我可以在Hashmaps中使用数组吗?如果是这样,则声明这种哈希图的确切语法是什么?谢谢 参考方案 数组也是对象。甚至像int[]这样的原始数组。Map<String,String[]> map = new HashMap<String,String[]>();

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…