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

标签 java multithreading unit-testing

这里我有三个简单的类:

第 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

这意味着thread1改变了count的值。那么,为什么 thread1 中的更改会影响 thread2,因为我没有使用任何“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 会出现在这种情况下?

最佳答案

每个线程都有一个内存 View 。如果不使用锁,则不能保证这些 View 在线程之间保持一致。因此,像上面那样共享一个变量(没有 volatile)会起作用,因为它跨线程可见,但会给您带来不可靠的结果。使用 volatile 关键字意味着变量在线程之间一致地读取。

参见 here ,特别注意:

Volatile fields are special fields which are used for communicating state between threads. Each read of a volatile will see the last write to that volatile by any thread; in effect, they are designated by the programmer as fields for which it is never acceptable to see a "stale" value as a result of caching or reordering.

关于java - 为什么即使不使用 volatile,在一个线程中修改共享变量也会影响另一个线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13376713/

相关文章:

java - 在 linux 下使用 JAI 的文件存储保存 JPG-Image

iphone - 使用运行循环联网

c - 将参数传递给 pthread

Eclipse 中的 Android 单元测试 : "Failed to launch test"

android - Kotlin 协程 : Switching context when testing an Android Presenter

visual-studio - Visual Studio 单元测试 - 如何访问外部文件?

java - 使用 JAVA Mail API 发送带附件的电子邮件而不存储在本地机器中

java - 需要 key.equals() java 的替代方案

java - 给 main 一个参数

c++ - 停止 winapi 线程时的错误行为