임계영역(critical section)은 여러 스레드가 동시에 접근할 때 문제가 발생할 수 있는 공유 자원(예: 변수, 데이터 구조 등)을 보호하기 위해 사용된다. 즉, 임계영역은 하나의 스레드가 해당 코드 블록을 실행할 때 다른 스레드가 접근하지 못하도록 하는 코드 영역이다. 이를 통해 데이터 무결성과 스레드 안전성을 보장할 수 있다.
임계영역의 필요성
스레드가 동시에 공유 자원에 접근할 때, 경합 조건(race condition)이 발생할 수 있다. 이러한 문제를 해결하기 위해 임계영역을 사용하여 하나의 스레드만 자원에 접근하도록 제한한다.
예시 코드 (C#)
다음은 lock
키워드를 사용하여 임계영역을 구현한 예시 코드이다.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace CriticalSectionExample
{
internal class Program
{
private static int number = 0;
private static readonly object _lockObject = new object();
private static void Increment()
{
for (int i = 0; i < 1000000; i++)
{
// 임계영역: 한 번에 하나의 스레드만 이 블록을 실행할 수 있다.
lock (_lockObject)
{
number++;
}
}
}
private static void Main(string[] args)
{
var t1 = new Task(Increment);
var t2 = new Task(Increment);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
Console.WriteLine($"Final value of number: {number}");
}
}
}
설명
lock
키워드:lock
은 지정된 객체(_lockObject
)를 사용하여 임계영역을 정의한다.lock
블록 내의 코드가 실행되는 동안 다른 스레드는_lockObject
를 사용한lock
블록에 들어올 수 없다.- 공유 자원 보호: 이 예시에서
number
는 공유 자원이며,lock
을 사용하여 동시 접근으로 인한 경합 조건을 방지한다.
작동 원리
- 스레드 A가
lock(_lockObject)
를 만나면_lockObject
를 잠근다. - 스레드 B가 같은
lock(_lockObject)
를 만나면, 스레드 A가 잠금을 해제할 때까지 기다린다. - 스레드 A가 임계영역의 실행을 마치고 잠금을 해제하면, 스레드 B가 임계영역에 들어갈 수 있다.
이로써 여러 스레드가 동시에 number
를 수정하지 않도록 하여 데이터 무결성을 유지할 수 있다.
'공부 > 게임서버' 카테고리의 다른 글
메모리 영역과 스레드 (0) | 2024.11.11 |
---|---|
재귀적 lock을 허용하지 않는 ReaderWriterLock 구현 예시 (0) | 2024.11.11 |
가시성 문제와 보장 방법 (0) | 2024.11.10 |
SpinLock / Interlocked.Exchange (0) | 2024.11.10 |
컨텍스트 스위칭 (0) | 2024.11.10 |