static int number = 0; (static이므로 스레드끼리 공유함)
thread 1에서 for loop을 통해 100000번 number++;
thread 2 '' number--;
이 경우 number은 0이 안나올 가능성이 아주 높다.
아마 27690 이런 값이 나올 가능성이 높다.
이유:
++나 --는 그 자체가 컴퓨터 행동의 최소단위(atomic)가 아니기 때문이다.
즉 number++는 사실
int temp = number;
temp -= 1;
number = temp;
의 세 단계의 최소단위, 혹은 atomic 한 operation으로 이루어져있는데,
스레드2에서 number가 -1로 초기화되었다가 바로 다음 차례에 스레드1에서 +1로 초기화되는 경우가 발생할 수 있다는 것이다. 왜냐하면 둘다 temp = number로 가져왔을 때 number가 0이었기 때문이다.
해결법:
1. Interlocked 클래스의 static 메소드 사용
ex. number++ -> Interlocked.increment(ref number)
장점: 편리함
단점: 이미 메소드로 갖춰진 기능만 사용가능.
2. Mutual Exclusive(상호배제) 하게 만들기
2-1) Monitor 사용
Monitor.Enter(object obj);
원하는 코드
Monitor.Exit(object obj);
2-2) lock 사용 (권장)
lock (obj)
{
코드
}
주의1:
obj는 일종의 열쇠같은 개념으로, 저기에 obj를 전달했다고 딱 obj에 대해서만 다른 스레드의 접근이 막히는 게 아님.
즉
lock (obj)
{
number++;
}
이면 number에 대한 다른 스레드들의 접근도 일시적으로 막히는 것임.
주의2:
저 원하는 코드 부분에서 return을 하게 되면 Exit가 실행되지 않으므로 공용 메모리들에 대한 모든 스레드들의 접근이 완전히 잠겨버림. 이를 Deadlock이라고 함.
'os > multithreading, parallel computing' 카테고리의 다른 글
메모리 정책(memory order), 메모리 장벽(memory fence/barrier) (0) | 2022.09.10 |
---|---|
lock-free atomic calculation (0) | 2022.09.10 |
멀티스레드 환경에서 발생하는 문제들 (0) | 2022.09.10 |
쓰레드와 프로세스, CPU 병렬 처리와 동시 처리 (0) | 2021.01.03 |