developer tip

주 스레드의 출력이 C #에서 먼저 나오는 이유는 무엇입니까?

copycodes 2020. 12. 30. 08:18
반응형

주 스레드의 출력이 C #에서 먼저 나오는 이유는 무엇입니까?


이 작은 프로그램을 작성했습니다.

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(".");
        }
    }
}

50 번 정도 실행했는데 콘솔의 첫 번째 문자는 항상 "O"였습니다. t스레드가 먼저 시작된 다음 메인이 계속 되기 때문에 나에게는 이상합니다 .

이에 대한 설명이 있습니까?


Thread.Start 먼저 실행을위한가 호출되는 스레드의 상태와 OS 일정을의 변화 때문에이는 아마 반면 메인 쓰레드가 이미 실행되고이 두 단계를 필요로하지 않습니다 . 이것이 아마도 메인 스레드의 명령문이 새로 생성 된 스레드의 명령문보다 먼저 실행되는 이유 일 것입니다. 스레드 실행 순서는 보장되지 않습니다.

Thread.Start 메서드

1) Thread.Start 메서드 운영 체제가 현재 인스턴스의 상태를 ThreadState.Running으로 변경하도록합니다.

2) 스레드가 ThreadState.Running 상태가되면 운영 체제가 실행을 예약 할 수 있습니다. 스레드는 ThreadStart가 나타내는 메서드의 첫 번째 줄에서 실행을 시작합니다.

편집 이것을 그래픽 형식으로 표현하면 이것을 더 명확하고 이해하기 쉽게 만드는 것 같습니다. 아래 다이어그램에서 스레드 실행 순서를 보여 주려고했습니다.

여기에 이미지 설명 입력


당신은 말한다 :

"t 스레드가 먼저 시작된 다음 메인이 계속되기 때문에 나에게는 이상합니다."

이것은 사실이 아닙니다. "메인"트레드는 이미 실행 중입니다. t.Start();실행되는, 이야기하는 OS가 t실행중인 상태입니다. OS는 "곧"스레드의 실행 시간을 예약합니다. 이것은 OS가 스레드 t가 시작될 때까지이 스레드의 실행을 중지하도록 지시하는 것과는 다릅니다 . 즉, Start리턴 될 때 스레드가 이미 실행을 시작했다는 보장이 없습니다.


대답이 아닌 조언이 더 많습니다 .

(당신이 달성하려는 것에 대한 실제 사용이 보이지 않으므로 문제를 자세히 설명하지 않은 개념의 사고 실험 / 증명으로 취급합니다.)


스레드가 제어를 위해 "경쟁"하도록하려면 메인 스레드에 앞서 시작하지 마십시오! 스레드를 생성하면 약간의 오버 헤드가 발생하고 메인 스레드가 이미 생성되었습니다 (다른 스레드를 생성하기 때문에). 메인 스레드와 작업자 스레드 모두에 대해 거의 동일한 기회를 찾고 있다면 작업자 스레드가 메인 스레드에 생성 될 때까지 기다렸다가 메인 스레드가 백그라운드 스레드에서 레이스를 시작할 때까지 기다려야합니다. 이것은 동기화 개체에 의해 달성 될 수 있습니다 .


실제로는 다음과 같습니다.

다음과 같이 메인 스레드와 백그라운드 스레드 모두에 표시되는 두 개의 ManualResetEvent를 선언해야 합니다.

private static ManualResetEvent backgroundThreadReady = new ManualResetEvent(false);
private static ManualResetEvent startThreadRace = new ManualResetEvent(false);

그런 다음 메인 스레드에서 다음과 같이 스레드가 초기화 될 때까지 기다려야합니다.

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");
    }
}

그리고 당신의 스레드에서 :

    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(".");
        }
    }

Please note that I could have used other waitable sync objects (mutex, autoreset event, even a critical section lock with some hack, I've just choose the simplest, fastest solution which can be extended easily).


Your code is non deterministic. Your code contains no thread primitives that would schedule priority of one thread over another or for one thread to wait for another.


Main process continue its next instructions set after invoking the thread ,It will take time to start thread method as light process.


It basically needs time to start the thread up. You are running the thread code at the same time as the rest of the first method. So taking into account the time it takes to start the thread and then get to the point where it is writing the "." does that make sense?

앱에 모든 것을 다시 시작할 수있는 일종의 재설정 버튼 (종료하지 않고)이있는 경우 첫 번째 문자가 "."라는 것을 알 수 있습니다. 스레드가 이미 존재하기 때문입니다.


메인 쓰레드가 생성 된 쓰레드보다 먼저 끝나는 이유는 오직 한 가지 이유는 쓰레드를 시작하는데 시간이 걸리기 때문입니다. 프로그램 속도를 높이기 위해 스레드를 사용하는 유일한 경우는 2 개의 작업을 동시에 실행할 수있는 경우입니다. 두 번째 루프를 먼저 완료하려면 Parallel.For 루프를 살펴보십시오 .c # ... 이는 for 루프의 각 루프를 동시에 실행합니다 (모두는 아니지만 PC가 처리 할 수있는만큼). )

참조 URL : https://stackoverflow.com/questions/30567847/why-does-the-main-threads-output-come-first-in-c

반응형