스레드의 임계영역
스레드 A, B 가있다.
A는 1을 100번 빼는 걸 반복하고, B는 1을 100번 더하는 걸 반복한다. 하지만 둘은 같은 데이터를 건들고 있다고 한다면, 어떤 상황이 일어날까?
차근차근 더하고 빼고 해서 0이 될 것 같지만 실상 확인해 보면 0이라는 숫자는 잘 나오지 않는다. 심지어 계산할 때마다 계산 값이 다르게 나온다. 왜 이럴까?
스레드는 num에 있는 값을 바로 바꾸지 않고, 먼저 참조한 후 계산한 값을 적용시킨다. 이렇다 보니 이러한 현상이 생긴다.
먼저 쓰레드 B가 100이라는 값을 참조한 후, 1을 더해 101을 대입했다. 하지만 동시에 값을 건드린 Thread A가 100이라는 값에서 1을 뺀 99라는 값을 대입해 버렸기 때문에 이러한 현상이 발생한다.
이렇게 둘 이상의 쓰레드가 동시에 실행하면 문제를 일으키는 곳을 임계영역이라고 한다.
스레드 동기화
이러한 스레드의 문제점을 해결해주는 것을 쓰레드 동기화(Synchronization)이라고 한다. 쓰레드 동기화는 두 가지 측면에서 활용할 수 있다.
- 메모리 영역의 동시접근이 발생할 때
- 메모리 영역 접근 쓰레드의 실행 순서를 지정해야 할 때
뮤텍스
뮤텍스 Mutual Exclusion의 줄임말로 동시접근을 허용하지 않는다는 말로, 쓰레드 동기화 방법으로 주로 사용된다.
뮤텍스는 화장실로 비유해 설명하기도 한다.
Thread A: 똑똑! 누구 있나요?
Thread B: 볼일 보고 있어요.....
Thread A: 똑똑.
Thread B: 이제 다 끝났어요. 나갑니다.
사용 과정은 다음과 같다.
- 들어갈 때 문을 잠그고 나올 때 연다
- 사용 중이라면, 밖에서 대기한다.
- 대기 중인 스레드는 여러 개가 될 수 있고, 순서대로 줄 서 있는다.
#include <mutex>
mutex value_mutex;
void increase_value()
{
value_mutex.lock(); // 문 잠금
value++;
cout << value << endl;
value_mutex.unlock(); // 문 잠금해제
}
마무리
스레드를 여러 개 사용할 때, 즉 멀티스레드 환경에선 임계영역, 실행 순서 등 신경 쓸 것이 많은 것 같다. 뮤텍스와 같은 동기화 방법을 남용하면 성능이 떨어지기도 하니 주의하자!
참고
'TCP-IP 소켓 프로그래밍' 카테고리의 다른 글
비동기 Notification IO 모델을 이해해보자 (0) | 2023.09.13 |
---|---|
epoll을 이해해보자 (0) | 2023.09.12 |
스레드와 프로세스의 차이를 이해해보자 (5) | 2023.09.11 |
Select 모델을 위한 Select 함수를 이해해보자 (0) | 2023.09.05 |
Nagle 알고리즘을 이해해보자 (0) | 2023.09.04 |