[C#] 멀티 스레드에서 lock 사용하기

동키·2024년 12월 24일

C#

목록 보기
9/12

C#의 lock 키워드는 스레드 간 동기화를 위해 사용되는 기능입니다. 여러 스레드가 동일한 리소스(예: 객체, 변수)에 동시에 접근할 때 데이터 무결성을 보장하고 데이터 경쟁 상태(Race Condition)를 방지합니다.

lock 키워드의 역할

스레드 간 데이터 보호

  • 여러 스레드가 동일한 리소스(메모리, 데이터)에 접근하거나 수정하려고 할 때, lock을 사용하여 한 번에 하나의 스레드만 접근 가능하도록 보장합니다.

임계 영역 보호

  • lock은 임계 영역(Critical Section)을 정의하여 해당 코드를 한 스레드가 실행하는 동안 다른 스레드는 대기하게 만듭니다.

기본 사용법

lock (object)
{
    // 보호할 코드
}
  • object: lock이 사용되는 동안 잠금(Lock)의 대상이 되는 객체입니다.
  • 보호할 코드: lock 블록 내의 코드는 한 번에 하나의 스레드만 실행할 수 있습니다.

예제 코드

동기화 없이 데이터 경쟁 상태 발생

using System;
using System.Threading;

class Program
{
    private static int counter = 0;

    static void Main()
    {
        Thread t1 = new Thread(IncrementCounter);
        Thread t2 = new Thread(IncrementCounter);

        t1.Start();
        t2.Start();

        t1.Join();
        t2.Join();

        Console.WriteLine($"최종 Counter 값: {counter}");
    }

    static void IncrementCounter()
    {
        for (int i = 0; i < 10000; i++)
        {
            counter++;
        }
    }
}
//출력 예시 (실행마다 달라짐):
최종 Counter 값: 15783
  • 이유:
    두 스레드가 counter에 동시에 접근하여 값을 수정하기 때문에 데이터 경쟁 상태가 발생하고 값이 손실됩니다.

lock을 사용한 동기화

using System;
using System.Threading;

class Program
{
    private static int counter = 0;
    private static readonly object lockObject = new object();

    static void Main()
    {
        Thread t1 = new Thread(IncrementCounter);
        Thread t2 = new Thread(IncrementCounter);

        t1.Start();
        t2.Start();

        t1.Join();
        t2.Join();

        Console.WriteLine($"최종 Counter 값: {counter}");
    }

    static void IncrementCounter()
    {
        for (int i = 0; i < 10000; i++)
        {
            lock (lockObject)
            {
                counter++;
            }
        }
    }
}

//최종 Counter 값: 20000
  • 결과:
    lock을 사용하여 한 스레드가 counter++를 수행하는 동안 다른 스레드는 대기합니다. 데이터 손실이 발생하지 않습니다.

lock의 동작 방식

잠금(Locking):

  • 스레드가 lock 블록에 들어오면 지정된 객체(lockObject)에 잠금을 설정합니다.

대기(Waiting):

  • 다른 스레드가 같은 객체를 잠그려고 하면 현재 잠금이 해제될 때까지 대기합니다.

해제(Releasing):

  • lock 블록을 벗어나면 객체의 잠금이 해제됩니다.

요약

  • lock 키워드는 멀티스레드 환경에서 공유 자원을 안전하게 보호하기 위해 사용됩니다.
  • 동작 방식:
    1. 한 스레드가 접근: lock 블록에 진입하여 작업 수행.
    2. 다른 스레드 대기: 현재 작업이 완료되고 잠금이 해제될 때까지 대기.
  • 주의사항: 데드락 방지, 최소한의 코드 잠금, 동일한 잠금 객체 사용.

lock은 멀티스레드 프로그래밍에서 가장 간단하고 안전한 동기화 방법 중 하나입니다. 하지만 더 정교한 동기화가 필요한 경우, Monitor나 다른 동기화 도구를 고려할 수 있습니다.

profile
오키동키

0개의 댓글