C# Rookiss Part4 ๊ฒ์์๋ฒ : Interlocked
๐โโ๏ธInterlocked
๐ช๊ฒฝํฉ ์กฐ๊ฑด (Race Condition)
2๋ฒ ํ ์ด๋ธ์์ ์ฝ๋ผ ํ๋๋ฅผ ์ฃผ๋ฌธํ๊ณ ์ฃผ๋ฌธํํฉ์ ์ฌ๋ผ์ด ์ง์ 3๋ช ์ด ๋์์ ์ฃผ๋ฌธํํฉ์ ๋ณด๊ณ ์ฝ๋ผ๋ฅด 2๋ฒ ํ ์ด๋ธ์ ์ค ๊ฒฐ๊ตญ 2๋ฒ ํ ์ด๋ธ์ ์ฝ๋ผ๋ฅผ 3๊ฐ ๋ฐ์
์์๋ฅผ ์งํค์ง ์๊ณ ๋์๋ค๋ฐ์ ์ผ๋ก ์ผ์ ํด์ ์๊ธด ๋ฌธ์
- ๊ฒฝํฉ ์กฐ๊ฑด ์์
static int number = 0;
static void Thread_1()
{
for (int i = 0; i < 100000; i++)
number++;
}
static void Thread_2()
{
for (int i = 0; i < 100000; i++)
number--;
}
static void Main(string[] args)
{
Task t1 = new Task(Thread_1);
Task t2 = new Task(Thread_2);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
Console.WriteLine(number);
}
100000์ ๋ํ๋ ์ฐ๋ ๋์ 100000์ ๋นผ๋ ์ฐ๋ ๋
- 0์ด ์๋๋ผ ๋ค๋ฅธ ๊ฒฐ๊ณผ ๊ฐ์ด ๋์ด
- ์ด์ ๋ number++, numberโ๊ฐ ์์์ ์ผ๋ก ์ฒ๋ฆฌ ๋๋๊ฒ์ด ์๋๊ธฐ ๋๋ฌธ
number++; // ์ด์
๋ธ๋ฆฌ์ธ์ด๋ก ๋ฐ๊ณผ ๊ฐ์ด ์ฒ๋ฆฌ ๋จ
int temp = number;
temp += 1;
number = temp;
๐ชInterlocked
- ์์์ ์ผ๋ก ์ฒ๋ฆฌํด์ฃผ๋ ํจ์
- Interlocked ๊ณ์ด์ ํจ์
- ๊ฐ์์ฑ ๋ฌธ์ ๊น์ง ํด๊ฒฐํจ - ๋ฉ๋ชจ๋ฆฌ๋ฒ ๋ฆฌ์ด๊ฐ ์จ์ด์์
- volatile์ด ํ์์์
static int number = 0;
static void Thread_1()
{
// atomic = ์์์ฑ
for (int i = 0; i < 100000; i++)
// All or Nothing
Interlocked.Increment(ref number); // ref๋ก ์ฐธ์กฐ๋ฅผ ํด์ ์ง์ ๊ฐ์ ์ฌ๋ฆฐ๋ค
}
static void Thread_2()
{
for (int i = 0; i < 100000; i++)
Interlocked.Decrement(ref number);
}
static void Main(string[] args)
{
Task t1 = new Task(Thread_1);
Task t2 = new Task(Thread_2);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
Console.WriteLine(number);
}
interlocked๊ณ์ด ํจ์๋ก ํด๊ฒฐ๊ฐ๋ฅ
- ๋ฉํฐ์ฐ๋ ๋์ ํจ์
int pre = number;
Interlocked.Increment(ref number);
int next = number;
์ธ๋ป๋ณด๋ฉด next๋ pre๋ณด๋ค 1ํด๊ฒ ๊ฐ์ง๋ง ์์์๋ค
์ฑ๊ธ ์ฐ๋ ๋์์๋ ๊ฐ๋ฅํ์ง๋ง ๋ฉํฐ์ฐ๋ ๋์์๋ ๋๊ตฐ๊ฐ๊ฐ ๋ณด๊ณ ๊ฐ์ด ๋ฐ๋์ ์๊ธฐ ๋๋ฌธ!!
int afterValue = Interlocked.Increment(ref number);
๊ฐ์ ๋นผ์ฌ๋ ค๋ฉด ์ด๋ ๊ฒ ํด์ผ๋จ