为什么主线程的输出在C#中排在第一位?

KOB*_*KOB 56 c# multithreading

我写了这个小程序:

class Program
{
    static void Main(string[] args)
    {
        Thread t = new Thread(WriteX);
        t.Start();

        for (int i = 0; i < 1000; i++)
        {
            Console.Write("O");
        }
    }

    private static void WriteX()
    {
        for (int i = 0; i < 1000; i++)
        {
            Console.Write(".");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我跑了大约五十次,控制台上的第一个字符总是"O".这对我来说很奇怪,因为t线程首先启动然后主要继续.

这有什么解释吗?

Adi*_*dil 53

这可能是因为Thread.Start首先使线程的状态就调用它和操作系统调度它的执行的变化,而主线程已经在运行,并不需要这两个步骤.这可能是主线程中的语句首先执行而不是新创建的线程中的语句的原因.请记住,不保证线程执行的顺序.

Thread.Start方法

1)Thread.Start方法使操作系统将当前实例的状态更改为ThreadState.Running.

2)一旦线程处于ThreadState.Running状态,操作系统就可以安排它执行.线程开始在ThreadStart表示的方法的第一行执行

编辑在我看来,以图形形式表示这将使这更加清晰和易懂.我试图在下图中显示线程执行的顺序.

在此输入图像描述


Mar*_*ijn 20

你说:

"这对我来说很奇怪,因为t线程首先开始然后主线继续."

这不是真的."主要"胎面已经开始运转.当t.Start();被执行时,OS被告知t处于运行状态.然后操作系统将"很快"安排线程的执行时间.除了指示操作系统在线程t启动之前停止执行此线程之外,这是其他内容.换句话说,Start返回时,无法保证线程已经开始执行.


mg3*_*0rg 13

更多的建议而非答案:

(请注意,我认为你想要实现的目标没有现实用途,因此我将你的问题视为思想实验/未详细解释的概念证据.)


如果你希望你的线程"竞争"控制,不要让你的主线程开始!创建一个线程有一些开销,你的主线程已经创建(因为它创建了你的另一个线程).如果您正在为主线程和工作线程寻找大致相等的机会,则应等待在主线程中创建工作线程并等待主线程在后台线程中开始竞争.这可以通过同步对象来实现.


在实践中,它看起来像这样:

你应该声明两个对主线程和后台线程都可见的ManualResetEvent,如下所示:

private static ManualResetEvent backgroundThreadReady = new ManualResetEvent(false);
private static ManualResetEvent startThreadRace = new ManualResetEvent(false);
Run Code Online (Sandbox Code Playgroud)

然后在你的主线程中,你应该等待你的线程被初始化,如:

static void Main(string[] args)
{
    Thread t = new Thread(WriteX);
    t.Start();
    backgroundThreadReady.WaitOne(); // wait for background thread to be ready

    startThreadRace.Set();           // signal your background thread to start the race
    for (int i = 0; i < 1000; i++)
    {
        Console.Write("O");
    }
}
Run Code Online (Sandbox Code Playgroud)

在你的线程中:

    private static void WriteX()
    {
        backgroundThreadReady.Set(); // inform your main thread that this thread is ready for the race

        startThreadRace.WaitOne();   // wait 'till the main thread starts the race
        for (int i = 0; i < 1000; i++)
        {
            Console.Write(".");
        }
    }
Run Code Online (Sandbox Code Playgroud)

请注意,我可以使用其他可等待的同步对象(互斥,自动复位事件,甚至是关键部分锁定和一些黑客攻击,我只选择最简单,最快速的解决方案,可以轻松扩展).


Kev*_*vin 5

您的代码是不确定的。您的代码不包含任何线程原语,这些原语会调度一个线程相对于另一个线程的优先级,或者使一个线程等待另一个线程的优先级。

  • 那不能回答问题。 (6认同)
  • 询问者已经认为是这种情况,因此是问题所在。 (2认同)