멀티쓰레드 프로그래밍

Locking

우대비 2024. 2. 23. 21:40
반응형

Locking은 C#에서 동시성을 관리하고 여러 스레드 간의 데이터 일관성을 유지하는 기본적인 메커니즘 중 하나입니다. Lock은 특정 코드 영역에 동시에 하나의 스레드만 접근할 수 있도록 보장하여

경쟁 조건(race conditions)과 같은 문제를 방지합니다.

 

Lock 구현의 기본 원리:

  1. 상호 배제(Mutual Exclusion): 어떤 스레드가 공유 자원을 사용하고 있을 때, 다른 스레드는 그 자원을 사용할 수 없어야 합니다. 이는 한 번에 하나의 스레드만이 특정 코드 섹션(임계 영역)을 실행할 수 있도록 보장합니다.
  2. 진행(Progress): 공유 자원에 대한 접근 권한을 요청하는 스레드들 중에서 선택하는 것은 임의적이어서는 안 되며, 잠금을 획득하기 위해 영원히 대기하는 스레드가 없어야 합니다.
  3. 한정 대기(Bounded Waiting): 한 스레드가 잠금을 요청한 후 다른 스레드가 무한히 잠금을 획득하는 상황을 방지하여, 각 스레드가 결국은 잠금을 획득할 수 있는 기회를 보장합니다.

 

C#에서는 lock 키워드를 사용하여 간단하게 임계 영역을 생성할 수 있으며,

내부적으로 Monitor 클래스를 사용합니다.

아래는 간단한 lock 구현 예시입니다:

using System;
using System.Threading;

public class LockExample
{
    private static readonly object _locker = new object(); // Lock 객체
    private static int _sharedResource = 0;

    public static void Main()
    {
        Thread thread1 = new Thread(IncrementResource);
        Thread thread2 = new Thread(DecrementResource);

        thread1.Start();
        thread2.Start();

        thread1.Join();
        thread2.Join();

        Console.WriteLine($"Final resource value: {_sharedResource}");
    }

    private static void IncrementResource()
    {
        lock (_locker) // 임계 영역 시작
        {
            _sharedResource++; // 공유 자원을 안전하게 수정
            Console.WriteLine($"Resource incremented to {_sharedResource}");
        } // 임계 영역 끝
    }

    private static void DecrementResource()
    {
        lock (_locker) // 임계 영역 시작
        {
            _sharedResource--; // 공유 자원을 안전하게 수정
            Console.WriteLine($"Resource decremented to {_sharedResource}");
        } // 임계 영역 끝
    }
}

위의 예제에서는 여러 스레드가 count 변수를 증가시키려고 할 때 lock 키워드를 사용하여 동시성 문제를 방지합니다. _lockObject는 공유 자원에 대한 접근을 동기화하는 데 사용되는 객체입니다.

 

lock 블록 내의 코드는 한 번에 하나의 스레드만 실행할 수 있으므로, count 변수는 동시에 여러 스레드에 의해 변경되지 않습니다.

 

lock (_lockObject) 구문은 다음과 같은 방식으로 작동합니다:

  1. 현재 스레드가 _lockObject에 대한 잠금을 획득하려고 시도합니다.
  2. 만약 _lockObject가 이미 다른 스레드에 의해 잠겨있다면, 현재 스레드는 그 잠금이 해제될 때까지 대기합니다. 이 대기 상태에서는 스레드가 실행을 중지하고 잠금이 해제될 때까지 기다립니다.
  3. _lockObject에 대한 잠금을 획득하면, 현재 스레드는 lock 블록 내의 코드를 실행합니다.
  4. lock 블록의 코드 실행이 완료되면, 잠금은 자동으로 해제되고, 다른 스레드가 잠금을 획득할 수 있게 됩니다.

 

 

반응형
LIST

'멀티쓰레드 프로그래밍' 카테고리의 다른 글

Context Switching  (0) 2024.02.26
SpinLock  (0) 2024.02.23
DeadLock  (0) 2024.02.23
Interlocked  (0) 2024.02.23
memory barrier  (0) 2024.02.23