Development Tip

멀티 스레딩 : 언제 조인을 사용합니까?

yourdevel 2020. 11. 27. 21:32
반응형

멀티 스레딩 : 언제 조인을 사용합니까?


myThread.Join();다른 스레드가 끝날 때까지 스레드를 차단하고 싶을 때 사용한다고 온라인에 표시됩니다 . (내가 이해하지 못하는 것 중 하나는 스레드가 여러 개인 경우입니다).

그러나 일반적으로 나는 언제 사용 .Join()할지 또는 유용한 조건을 얻지 못합니다 . 제가 4 학년 인 것처럼 설명해 주 시겠어요? 이해하기 매우 간단한 설명이 내 답변 투표를받을 것입니다.


어떤 종류의 계산을 수행하기 위해 일부 작업자 스레드를 시작한 다음 모든 결과를 사용하여 나중에 작업을 수행한다고 가정 해 보겠습니다.

List<Thread> workerThreads = new List<Thread>();
List<int> results = new List<int>();

for (int i = 0; i < 5; i++) {
    Thread thread = new Thread(() => {
        Thread.Sleep(new Random().Next(1000, 5000));
        lock (results) {
            results.Add(new Random().Next(1, 10));
        }
    });
    workerThreads.Add(thread);
    thread.Start();
}

// Wait for all the threads to finish so that the results list is populated.
// If a thread is already finished when Join is called, Join will return immediately.
foreach (Thread thread in workerThreads) {
    thread.Join();
}

Debug.WriteLine("Sum of results: " + results.Sum());

오, 그렇습니다. Random을 그런 식으로 사용하지 마십시오. 저는 단지 최소한의 이해하기 쉬운 예제를 작성하려고했습니다. 시드가 시계를 기반으로하기 때문에 시간에 너무 가깝게 새 Random 인스턴스를 생성하면 실제로 무작위가 아닙니다.


다음 코드 스 니펫에서 기본 스레드는 생성 된 모든 스레드가 완료 될 때까지 대기하도록하는 Join ()호출합니다 .

static void Main()
{
    Thread regularThread = new Thread(ThreadMethod);
    regularThread.Start();

    Thread regularThread2 = new Thread(ThreadMethod2);
    regularThread2.Start();

    // Wait for spawned threads to end.
    regularThread.Join();
    Console.WriteLine("regularThread returned.");

    regularThread2.Join();
    Console.WriteLine("regularThread2 returned.");
}

스레드 풀에서 스레드를 스핀 업하는 경우 (예 : QueueUserWorkItem 사용) Join은 해당 백그라운드 스레드를 기다리지 않습니다. AutoResetEvent 사용과 같은 다른 메커니즘을 구현해야합니다.

스레딩에 대한 훌륭한 소개는 Joe Albahari의 무료 Threading in C #을 읽는 것이 좋습니다 .


이것은 Thread의 사용법을 보여주는 매우 간단한 프로그램 Join입니다. 더 나은 이해를 위해 내 의견을 따르십시오.이 프로그램을 그대로 작성하십시오.

    using System;
    using System.Threading;


    namespace ThreadSample
    {
        class Program
        {
            static Thread thread1, thread2;
            static int sum=0;
            static void Main(string[] args)
            {
                start();
                Console.ReadKey();
            }
            private static void Sample() { sum = sum + 1; }
            private static void Sample2() { sum = sum + 10; }

            private static void start() 
            {    
                thread1 = new Thread(new ThreadStart(Sample));
                thread2 = new Thread(new ThreadStart(Sample2));
                thread1.Start();
                thread2.Start();
             // thread1.Join(); 
             // thread2.Join();
                Console.WriteLine(sum);
                Console.WriteLine();
            }
       }
}

1. 처음 그대로 실행 (코멘트 포함) : 결과는 0 (초기 값) 또는 1 (스레드 1 완료시) 또는 10 (또는 스레드 완료)

2. 주석thread1.Join()제거하고 실행 : 결과는 항상 1보다 커야합니다 . 왜냐하면 실행 thread1.Join()되고 스레드 1은 합계를 얻기 전에 완료되어야하기 때문입니다.

3. 모든 코드를 제거하고 실행 : 결과는 항상 11이어야합니다.


조인은 주로 코드를 진행하기 전에 스레드 (또는 여러 스레드)가 종료 될 때까지 기다려야 할 때 사용됩니다.

For this reason is also particular useful when you need to collect result from a thread execution.

As per the Arafangion comment below, it's also important to join threads if you need to do some cleaning/housekeeping code after having created a thread.


Join will make sure that the treads above line is executed before executing lines below.


Another example, when your worker thread let's say reads from an input stream while the read method can run forever and you want to somehow avoid this - by applying timeout using another watchdog thread:

// worker thread
var worker = new Thread(() => {
    Trace.WriteLine("Reading from stream");

    // here is the critical area of thread, where the real stuff happens
    // Sleep is just an example, simulating any real operation
    Thread.Sleep(10000);

    Trace.WriteLine("Reading finished");
}) { Name = "Worker" };
Trace.WriteLine("Starting worker thread...");
worker.Start();

// watchdog thread
ThreadPool.QueueUserWorkItem((o) => {
    var timeOut = 5000;
    if (!worker.Join(timeOut))
    {
        Trace.WriteLine("Killing worker thread after " + timeOut + " milliseconds!");
        worker.Abort();
    }
});

Adding a delay of 300ms in method "Sample" and a delay of 400ms in "Sample2" from devopsEMK's post would make it easier to understand.

By doing so you can observe that by removing the comment from "thread1.Join();" line, the main thread waits for the "thread1" to complete and only after moves on.

참고URL : https://stackoverflow.com/questions/4485770/multithreading-when-would-i-use-a-join

반응형