..."/> ...">

>백엔드 개발 >C++ >내 'foreach' 루프와 Lambda 스레딩은 C#에서 안전합니까?

내 'foreach' 루프와 Lambda 스레딩은 C#에서 안전합니까?

Barbara Streisand
Barbara Streisand원래의
2025-01-22 07:06:16628검색

Is My `foreach` Loop and Lambda Threading Safe in C#?

C#의 foreach 루프 및 람다 표현식의 스레드 안전성 문제

다음 코드 조각을 분석해 보겠습니다.

<code class="language-csharp">foreach (Foo f in ListOfFoo)
{      
    Thread thread = new Thread(() => f.DoSomething());
    threads.Add(thread);
    thread.Start();
}</code>
<code class="language-csharp">foreach (Foo f in ListOfFoo)
{      
    Foo f2 = f;
    Thread thread = new Thread(() => f2.DoSomething());
    threads.Add(thread);
    thread.Start();
}</code>

스레드가 생성되었을 때와 동일한 루프 반복에서 각 스레드가 Foo 인스턴스의 메서드를 호출하도록 보장하는 코드 조각은 무엇입니까?

C# 5 이상에서는 클로저 범위 내의 변수 정의에 대한 컴파일러 변경으로 인해 두 코드 조각 모두 안전합니다. 그러나 C# 5 이전에는 두 번째 코드 조각만 안전했습니다.

첫 번째 코드 조각에서 f 변수는 루프 외부에 선언되어 실행 내내 계속 표시됩니다. 이는 클로저 범위에 f 인스턴스가 하나만 있음을 의미합니다. 따라서 f에 액세스하는 다른 스레드가 충돌하여 메서드 호출 오류가 발생할 수 있습니다.

이 문제를 완화하기 위해 두 번째 코드 조각에서는 루프 내부에 새 변수 f2를 선언합니다. 이렇게 하면 각 클로저 범위에 Foo 인스턴스에 대한 자체 참조 복사본이 있어 스레드별 안전한 메서드 실행이 보장됩니다.

다음 예에서는 이 문제를 보여줍니다.

<code class="language-csharp">static void Main()
{
    int[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    foreach (int i in data)
    {
        new Thread(() => Console.WriteLine(i)).Start();
    }

    Console.ReadLine();
}</code>

임시 변수를 사용하지 않으면 이 코드는 예측할 수 없고 잘못된 출력을 생성합니다. 이는 모든 스레드가 동일한 i 변수를 참조하고 foreach 값이 i 루프가 끝난 후 마지막 값이기 때문입니다.

따라서 스레드 안전성을 보장하려면 두 번째 코드 조각에 표시된 대로 foreach 루프 내에서 Lambda 표현식을 사용할 때 항상 로컬 변수의 복사본을 생성하는 것이 가장 좋습니다.

위 내용은 내 'foreach' 루프와 Lambda 스레딩은 C#에서 안전합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.