๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ–ฅ๏ธ/C#

[C#] ์Šค๋ ˆ๋“œ์˜ ํฌ๋ฆฌํ‹ฐ์ปฌ ์„น์…˜(Critical Section)

by HanaV 2023. 10. 11.
728x90
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 ๋˜๋ฉด์„œ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

728x90

"); wcs_do();