c# - Java 和 C# 线程处理数据同步的方式有何不同?

标签 c# java multithreading concurrency synchronization

在下面的 C# 代码中,t1 总是(对于我尝试过的次数)完成。

class MainClass
{
    static void DoExperiment ()
    {
        int value = 0;

        Thread t1 = new Thread (() => {
            Console.WriteLine ("T one is running now");
            while (value == 0) {
                //do nothing
            }
            Console.WriteLine ("T one is done now");
        });

        Thread t2 = new Thread (() => {
            Console.WriteLine ("T two is running now");
            Thread.Sleep (1000);
            value = 1;
            Console.WriteLine ("T two changed value to 1");
            Console.WriteLine ("T two is done now");
        });

        t1.Start ();
        t2.Start ();

        t1.Join ();
        t1.Join ();
    }

    public static void Main (string[] args)
    {
        for (int i=0; i<10; i++) {
            DoExperiment ();
            Console.WriteLine ("------------------------");
        }
    }
} 

但是在非常相似的Java代码中,t1永远不会(我尝试过的时候)退出:

public class MainClass {
static class Experiment {
    private int value = 0;

    public void doExperiment() throws InterruptedException {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {

                System.out.println("T one is running now");
                while (value == 0) {
                    //do nothing
                }
                System.out.println("T one is done now");
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("T two is running now");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                value = 1;
                System.out.println("T two changed value to 1");
                System.out.println("T two is done now");
            }
        }
        );

        t1.start();
        t2.start();

        t1.join();
        t1.join();
    }
}


public static void main(String[] args) throws InterruptedException {
    for (int i = 0; i < 10; i++) {
        new Experiment().doExperiment();
        System.out.println("------------------------");
    }
}

}

这是为什么?

最佳答案

我不确定 C# 中是如何发生的,但 Java 中发生的是 JVM 优化。 value 的值在 while 循环内不会改变,并且 JVM 会识别它并跳过测试并将咬合代码更改为类似的内容这个:

while (true) {
    // do nothing
}

为了在 Java 中修复此问题,您需要将 value 声明为 volatile :

private volatile int value = 0;

这将使JVM不会优化此while循环并检查value实际值> 在每次迭代开始时。

关于c# - Java 和 C# 线程处理数据同步的方式有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19710375/

相关文章:

C#声音是从哪个方向传来的?

Java 在我的字符串中添加双引号

java - spring出错时保留textbox的值

java - 在 Tomcat 9 上运行的多线程服务器

c# - 计算 linq Entity Framework 中的子匹配项

c# - C# 的 using 语句是否调用 Dispose on out 参数?

java - Google Drive API Java,身份验证仅在第一次时有效

c++ - 更新 CListCtrl 时 MFC 应用程序卡住

c++ - Boost::Thread/C++11 std::thread,想要在条件下唤醒工作线程

c# - StreamReader 和读取 XML 文件