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

时间:2019-06-15 11:20:37

标签: java c# multithreading

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

我基本上基于共享变量条件在两个线程中都有打印语句,但是当我在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”,并且程序永不终止(退出)。请解释一下获得不同输出的原因

1 个答案:

答案 0 :(得分:1)

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

具体来说,就我所知,在Java和C#上,在多核处理器上,不能保证一个线程看到另一个线程所做的事情,除非您有一个读取内存屏障,您可以通过同步读取来完成(还包括互斥,并且更昂贵,您在这里不需要)或不稳定的读写(更便宜,并且仅在不互斥的情况下保证其他线程可见性和发生)-如果您只有作家,读者谁只能读取,并且如果您要修改/读取的字段是原子值(在您的示例中就是这种情况)。

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