java - 在多线程环境中用 C# 和 Java 编写同一程序时获得不同的输出

标签 java c# multithreading

我有一个未初始化的共享 boolean 静态变量,并创建了两个线程,启动了一个线程,然后 hibernate 两秒,然后启动了第二个线程。

我基本上在两个线程中都有基于共享变量条件的打印语句,但在 c# 和 java 中运行时得到不同的输出

C# 代码:

class ThreadCache
    {
        public static bool shared;
        public static void Main()
        {
            new Thread(Meth1).Start();
            Thread.Sleep(2000);
            new Thread(Meth2).Start();
        }
        public static void Meth1()
        {
            while (!shared) { }
            Console.WriteLine("Hello");
        }
        public static void Meth2()
        {
            shared = true;
            Console.WriteLine("Hi");
        }
    }

Java 代码:

public class HiHello
{
    static boolean S1 = false;

    public static void main(String[] args) throws InterruptedException {
        new Thread(new Thread1(), "Thread 1").start();
        Thread.sleep(2000);
        new Thread(new Thread2(), "Thread 2").start();
    }

    private static class Thread1 implements Runnable
    {
        public void run()
        {
            while (!HiHello.S1) {}
            System.out.println("HELLO!");
        }
    }

    private static class Thread2 implements Runnable
    {
        public void run()
        {
            HiHello.S1 = true;
            System.out.println("HI!");
        }
    }
}

在 C# 中,无论我运行代码多少次,我都会得到输出“Hi”和“Hello”,但是当我在 java 中运行时,只会打印“Hi”,并且程序永远不会终止(退出)。请解释一下获得不同输出的原因

最佳答案

两个程序都有多线程/并发错误。行为上的差异与 C# 和 Java 如何处理线程的底层实现细节、它们的内存模型、它们如何与硬件交互以及运气有关。

具体来说,据我所知,在 Java 和 C# 中,在多核处理器上,无法保证一个线程可以看到另一个线程所做的事情,除非您有一个读内存屏障,您可以通过同步读取来完成该屏障(这还包括互斥性并且更昂贵,您在这里不需要)或 volatile 写/读(更便宜并且只提供其他线程可见性和发生之前保证而没有互斥性。如果您有只写的写入者,读者,那就太好了谁只读取,以及您正在修改/读取的字段是否是原子值(您的示例中就是这种情况)。

Volatile vs. Interlocked vs. lock

Happens-before rules in Java Memory Model

guarantee that up-to-date value of variable is always visible to several threads on multi-processor system

关于java - 在多线程环境中用 C# 和 Java 编写同一程序时获得不同的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56609872/

相关文章:

c++ - qDebug() 线程安全吗?

multithreading - 如何使用线程代替 perl/pdl 中的子例程循环

Java 8 并行流实际上并没有并行工作

c# - REST 服务中的 POST 请求为空

java - Spark没有注册输出操作,所以没有什么可执行的,但我正在写入文件

c# - 查看 c# 控制台应用程序参数

带有附件的 C# MailTo?

multithreading - 在pthread中,如何可靠地将信号传递给另一个线程?

java - SqlExceptionHelper.logExceptions int 类型的错误值 : WRAP

java - 如何调试无限循环的程序?