我有一个未初始化的共享布尔静态变量,并创建了两个线程,启动了一个线程,然后休眠了两秒钟,然后启动了第二个线程。
我基本上基于共享变量条件在两个线程中都有打印语句,但是当我在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”,并且程序永不终止(退出)。请解释一下获得不同输出的原因
答案 0 :(得分:1)
两个程序都有多线程/并发错误。行为上的差异与C#和Java如何处理线程的基本实现,它们的内存模型,它们与硬件的交互方式以及运气有关。
具体来说,就我所知,在Java和C#上,在多核处理器上,不能保证一个线程看到另一个线程所做的事情,除非您有一个读取内存屏障,您可以通过同步读取来完成(还包括互斥,并且更昂贵,您在这里不需要)或不稳定的读写(更便宜,并且仅在不互斥的情况下保证其他线程可见性和发生)-如果您只有作家,读者谁只能读取,并且如果您要修改/读取的字段是原子值(在您的示例中就是这种情况)。
Volatile vs. Interlocked vs. lock