스핀락(SpinLock) 구현하기 2/2
지난 포스팅에서는 스핀락을 화장실 앞에서 계속 기다리는 사람의 비유를 들어서 이해해보았는데요, 위키백과사전에 나와있는 정의는 다음과 같습니다.
우리가 대강 비슷하게 이해한 것 같습니다:) 이제는 이어서 spinLock클래스를 구현해봅시다. 지난 포스팅에서 문제였던 것은 바로 화장실에 동시에 두 사람이 들어가게 되어버리도록 spinLock.Acquire()를 작성했다는 것입니다. 이번에는 절대 두 사람이 동시에 들어갈 수 없도록 코드를 수정해봅시다. 이번에도 Interlocked 계열의 함수를 사용하겠습니다! 아래의 잘못된 코드를,
1
2
3
4
5
6
7
8
9
public void Acquire()
{
while (_locked)
{
// 잠김이 풀리기를 기다린다.
}
// 내꺼!
_locked = true;
}
아래의 코드로 바꾸었습니다.
1
2
3
4
5
6
7
8
9
10
11
12
public void Acquire()
{
while (true)
{
// CAS Compare-And-Swap
// 1을 넣어주기 전에 먼저 그 이전값이 0인지부터 체크한다.
int expected = 0;
int desired = 1;
if (Interlocked.CompareExchange(ref _locked, desired, expected) == 0)
break;
}
}
일단 코드가 전부 while문으로 들어왔습니다. 1) 계속 문이 열렸는지(0) 체크하다가 열렸으면(0) 바로 들어가서(1) 문을 닫는다.
while문 안에서 Interlocked계열 함수를 사용했기 때문에 원자적으로 실행되는 것은 보장할 수 있게 되었습니다! 코드를 실행해보면서 글을 마치겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.Data;
using System.Threading;
using System.Threading.Tasks;
namespace ServerCore
{
class SpinLock
{
volatile int _locked = 0;
public void Acquire()
{
while (true)
{
//// _locked 에 1을 넣되, 그 이전값이 0이면 break;
//int original = Interlocked.Exchange(ref _locked, 1);
//if (original == 0)
// break;
// CAS Compare-And-Swap
// 1을 넣어주기 전에 먼저 그 이전값이 0인지부터 체크한다.
int expected = 0;
int desired = 1;
if (Interlocked.CompareExchange(ref _locked, desired, expected) == 0)
break;
}
}
public void Release()
{
_locked = 0;
}
}
internal class Program
{
static int _num = 0;
static SpinLock _lock = new SpinLock();
static void Thread_1()
{
for (int i = 0; i < 1000000; i++)
{
_lock.Acquire();
_num++;
_lock.Release();
}
}
static void Thread_2()
{
for (int i = 0; i < 1000000; i++)
{
_lock.Acquire();
_num--;
_lock.Release();
}
}
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(_num);
}
}
}
이제 수건(?)의 개수가 안 세어져서 걱정할 일은 없겠군요!ㅎㅎㅎㅎ
이 글은 인프런의 '[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버' 강의를 참고하여 정리 목적으로 작성하였습니다. 감사합니다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

