[C#] μ€λ λμ ν¬λ¦¬ν°μ»¬ μΉμ (Critical Section)
public static void IncrementCounter()
{
for (int i = 0; i < 100000; i++) {
counter++;
}
}
μ λ©μλλ counterμ΄λΌλ λ³μλ₯Ό 100,000λ² λ°λ³΅ν΄μ 1μ© μ¬λ¦¬λ μμ
μ νλ€.
λ§μ½ μ΄ counter λ³μλ₯Ό κ°μ΄ μ¦κ°μν€λ μ€λ λκ° κ°μ΄ μμλμλ€κ³ ν΄λ³΄μ.
Thread t1 = new Thread(IncrementCounter);
Thread t2 = new Thread(IncrementCounter);
t1.Start();
t2.Start();
t1.Join();
t2.Join();
t1 μ€λ λλ 100,000, t2 μ€λ λλ 100,000μ μ¬λ €μ countλ 200,000μ΄ λμ΄μΌν κ² κ°μ§λ§, μ€μ λ‘ μ€νμμΌλ³΄λ©΄ λ§€λ² λ€λ₯΄κ² λμ€λ κ²μ λ³Ό μ μλ€.




μ μ΄λ° μΌμ΄ μΌμ΄λ κΉ?
μ¬λ¬ μ€λ λκ° λμμ counterλ₯Ό λμμ μ¦κ°μν€λ €κ³ μλνκΈ° λλ¬Έμ κ²½μ μν(Race condition)κ° λ°μνκ² λλ€. μλ₯Ό λ€μ΄ νμ¬ counter κ°μ΄ 10μ΄λΌλ©΄,
1. t1κ³Ό t2κ° νμ¬ counter κ°μ 10μΌλ‘ μ½λλ€.
2. t1μ΄ counter κ°μ 11λ‘ μ¦κ°μν€κ³ μ μ₯νλ€.
3. t2λ counter κ°μ 10μΌλ‘ μκ³ μκΈ° λλ¬Έμ 11μ λ€μ μ μ₯νλ€.
μ΄λ κ² μ¬λ¬ μ€λ λκ° λμμ 곡μ λ³μμ μ κ·Όνκ³ μμ νλ €κ³ ν λ, κ²½μ μνλ‘ μΈν΄ λ°μ΄ν° μΌκ΄μ±μ΄ κΉ¨μ§ μ μλ€. μ΄λ₯Ό λ§κΈ° μν΄ ν¬λ¦¬ν°μ»¬ μΉμ μ λ§λ€μ΄ μ¬μ©νλ€.
ν¬λ¦¬ν°μ»¬ μΉμ (Critical Section)
λ©ν° μ€λ λ νκ²½μμ 곡μ μμμ λμμ μ κ·Όνλ κ²μ μ μ΄νκ³ λκΈ°ννλ λ° μ¬μ©λλ μ½λ μμμ ν¬λ¦¬ν°μ»¬ μΉμ μ΄λΌκ³ νλ€. μ¦, ν λ²μ ν μ€λ λλ§ μ¬μ©ν μ μλ μμμ΄λ€.
lock ν€μλ
ν¬λ¦¬ν°μ»¬ μΉμ
μ lock ν€μλλ₯Ό μ¬μ©ν΄μ κ°λ¨νκ² κ΅¬νν μ μλ€.
μμ μμμμ lockμ νλ©΄ μ΄λ κ² λλ€.
private static object lockObject = new object();
for (int i = 0; i < 100000; i++) {
lock (lockObject)
{
counter++;
}
}
μ΄ λ, lockμ κΌ μ°Έμ‘°ν λ°μ΄ν° νμ μΌλ‘ μ μΈν΄μ€μΌνλ€. object, string λ λ€ λλ€.
μ΄μ lock ν€μλλ‘ λλ¬μμΈ counter λ³μκ° μ¦κ°νλ λΆλΆμ ν¬λ¦¬ν°μ»¬ μΉμ μ΄ λλ€. μ΄ λΆλΆμ μ΄μ νλμ μ€λ λκ° μ€νλ λμ λ€λ₯Έ μ€λ λκ° κ°μ νμ§ λͺ»νλ€.

κ²°κ³Ό λν 200,000μ΄ μλμ€λ κ²μ νμΈν μ μλ€.
Monitor ν΄λμ€
Monitor ν΄λμ€λ lockκ³Ό λμΌν μν μ νλ Monitor.Enter()κ³Ό Monitor.Exit()μ΄ μλ€. (μ¬μ€ lockμ΄ μ΄ λ©μλ λ κ°μ§λ‘ μ΄λ£¨μ΄μ Έ μλ€)
public static void IncrementCounter()
{
for (int i = 0; i < 100000; i++) {
Monitor.Enter(lockObject);
counter++;
Monitor.Exit(lockObject);
}
}
Monitor ν΄λμ€μλ Monitor.Wait()κ³Ό Monitor.Pulse() λ©μλλ μλ€. μ΄ λ λ©μλλ λ§ κ·Έλλ‘ μ€λ λλ₯Ό λκΈ°/μ€ν λκΈ°μνλ‘ νλ λ©μλμ΄λ€.
public static void Sender()
{
for (int i = 0; i < 3; i++) {
lock (lockObject) {
Console.WriteLine("Sender is typing a message...");
Thread.Sleep(1000);
message = "Message " + (i + 1);
Console.WriteLine("Sender sent: " + message);
Thread.Sleep(500);
Console.WriteLine("Pulsing Receiver...");
Monitor.Pulse(lockObject); Thread.Sleep(500);
Console.WriteLine("Sender is waiting Receiver to receive the message...");
Monitor.Wait(lockObject); Thread.Sleep(500);
}
}
}
public static void Receiver()
{
for (int i = 0; i < 3; i++) {
lock (lockObject) {
Console.WriteLine("Receiver is waiting for a message...");
Monitor.Wait(lockObject); Thread.Sleep(500);
Console.WriteLine("Receiver received: " + message);
Thread.Sleep(500);
Console.WriteLine("Pulsing Sender...");
Monitor.Pulse(lockObject); Thread.Sleep(500);
}
}
}
μ΄ λ κ°λ₯Ό μ€λ λ λ κ°μ κ°κ° μ€νμν€λ©΄,
Receiver is waiting for a message...
Sender is typing a message...
Sender sent: Message 1
Pulsing Receiver...
Sender is waiting Receiver to receive the message...
Receiver received: Message 1
Pulsing Sender...
Receiver is waiting for a message...
Sender is typing a message...
Sender sent: Message 2
Pulsing Receiver...
Sender is waiting Receiver to receive the message...
Receiver received: Message 2
Pulsing Sender...
Receiver is waiting for a message...
Sender is typing a message...
Sender sent: Message 3
Pulsing Receiver...
Sender is waiting Receiver to receive the message...
Receiver received: Message 3
Pulsing Sender...
μ΄λ κ² wait λλ©΄μ λ€λ₯Έ μ€λ λκ° μ€νλλ κ²μ λ³Ό μ μλ€.