01강 Lock 기초
int temp = number; 등과 같이 쓰는 작업이 들어갔을 시 문제가 생기는 부분이 있을 수 있음
⇒ 임계영역 (다른 스레드가 참견하면 문제가 생기는 코드 영역)
임계영역을 만들기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Program{
static int num = 0;
static object obj = new object();
static void Tread_1(){
for(int i=0; i< 10000; i++){
Monitor.Enter(obj);
{
num++;
}
Monitor.Exit(obj);
}
}
}
Monitor.Enter
Monitor.Exit
을 사용하여 임계영역 지켜내기
스토리와 비교
- 화장실에 들어가서
- 문을 잠그기
- 문을 잠금 풀기
2와 3 사이에 쓰고자 하는 코드를 적어줌
상호배제의 개념 (Mutual Exclusive)
- 2와 3 사이의 코드는 그 스레드만 처리할 것임 (싱글 스레드같이)
Monitor.Exit 을 해주지 않고 끝냈을 때
아래와 같이 스레드2에 데드락 현상이 일어난다 (무한 대기)
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
class Program{
static int num = 0;
static object obj = new object();
static void Tread_1(){
for(int i=0; i< 10000; i++){
Monitor.Enter(obj);
{
num++;
return;
}
Monitor.Exit(obj);
}
}
static void Tread_2(){
for (int i=0; i<10000; i++){
Monitor.Enter(obj);
num--;
Monitor.Exit(obj);
}
}
}
- 스레드 1에서 Monitor.Enter(~)을 해준후, .Exit(~)을 해주지 않고 return 을 하여 스레드를 끝냄으로써 스레드2가 데드락 상태에 빠진다.
일반적인 상황에서 사용하는 법
- try ~ finally구문을 사용한다
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
class Program{
static int num = 0;
static object obj = new object();
static void Tread_1(){
for(int i=0; i< 10000; i++){
try{
Monitor.Enter(obj);
num++
return;
}
finally{
Monitor.Exit(obj);
}
}
}
static void Tread_2(){
for (int i=0; i<10000; i++){
Monitor.Enter(obj);
num--;
Monitor.Exit(obj);
}
}
}
try ~ 뒤에 있는 finally가 try 에 결과와는 상관 없이 무조건 한번 실행되기 때문에
숫자를 0으로 나누던가 하는 등의 오류때문에 프로그램이 Exit 없이 종료 시 이를 해결할 수 있게 됨
- 위 코드에서는 return 을 해주더라도 finally가 실행됨
Lock 을 사용한 데드락 해결 (더 일반적, 추천)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Program{
static int num = 0;
static object obj = new object();
static void Tread_1(){
for(int i=0; i< 10000; i++){
lock(obj){
num++
}
}
}
...
obj 라는 것을 lock 으로 잠구고 {}을 빠져나가면 다시 알아서 열어준다