일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- compiler
- Python
- 동적계획법
- scikit-learn
- 기술면접
- Controller
- disjoint set
- top-down
- dto
- Django
- Java
- 유니온 파인드
- Android Studio
- 우선순위큐
- 직무면접
- 엔테크서비스
- 벨만 포드 알고리즘
- BufferedReader
- union-find
- bottom-up
- spring boot
- 거쳐가는 정점
- onclick
- 최단경로
- 다익스트라
- 음수가 포함된 최단경로
- kmeans
- clean code
- 코딩테스트
- 플로이드 와샬
- Today
- Total
춤추는 개발자
[OS] 멀티 스레드의 동기화 본문
앞선 포스팅에서 언급했듯이 스레드는 Stack영역을 제외한 나머지 메모리 영역을 공유합니다. 이때 공유 자원에 둘 이상의 스레드가 동시에 접근하면서 문제가 발생할 수 있습니다.
특정 스레드가 다른 스레드에서 사용 중인 변수나 자료구조에 접근하여 예상과는 엉뚱한 값을 읽어오거나 수정하는 문제로 아래와 같은 상황이 발생합니다.
이와 같이 하나의 변수에 둘 이상의 스레드가 접근하며 예상과는 다른 결과가 나올 수 있습니다. 이러한 상황을 해결하기 위한 방법이 멀티 스레드의 동기화입니다. 공유 변수에 대한 접근을 하나의 스레드로 제한함으로써 정확한 값을 리턴받을 수 있습니다. 윈도우는 다양한 동기화 관련 API를 제공하여 프로그래머가 상황에 따라 적절한 동기화 기법을 선택할 수 있습니다.
종류 | 용도 |
임계 영역 | 공유 리소스에 대해 오직 하나의 스레드 접근만 허용한다. (한 프로세스에 속한 스레드에만 사용 가능) |
뮤텍스 | 공유 리소스에 대해 오직 하나의 스레드 접근만 허용한다. (서로 다른 프로세스에 속한 스레드에도 사용 가능) |
이벤트 | 특정 사건 발생을 다른 스레드에 알린다. |
세마포어 | 한정된 개수의 자원을 여러 스레드가 사용하려고 할 때, 접근을 제한한다. |
임계 영역
- 유저 영역 메모리에 존재하는 구조체입니다. 다른 프로세스가 접근할 수 없으므로 한 프로세스에 속한 스레드 동기화에만 사용할 수 있습니다.
- 일반적인 동기화 객체보다 빠르고 효율적입니다.
- 자바에서는 임계 영역을 보호할 수 있는 메커니즘을 제공하며, 실제 스레드들이 동기화되도록 개발자가 구현해야 합니다.
lock, monitor, synchronized
- 동기화 문제가 발생하는 최소 단위는 객체이며, 동기화 문제 발생 지점은 객체가 소유한 내부 변수가 됩니다. 자바는 모든 객체에 락(lock or 세마포어)을 포함시키며, 모든 객체가 인스턴스화 될 때, Heap 영역에 객체가 저장될 때, 자동으로 생성됩니다.
락은 Synchronized 키워드를 통해 사용합니다. 해당 키워드를 사용하면 객체의 락을 검사하고, 락의 현재 사용 여부를 검사함으로써 각 객체를 보호합니다.
public synchronized void Method() {
}
public void normalMethod() {
synchronizer(/* 동기화할 객체 또는 클래스 명 */) {
// 임계영역 코드
}
}
변수 외에 메소드에서 일부분만 동기화하고 싶은 경우, 특정 블록 동기화 방법을 사용하면 됩니다.
wait(), notify(), notifyAll()
- 동기화된 블록에서 스레드 간의 통신하기 위해서는 wait(), notify(), notifyAll() 메소드를 사용해야 합니다.
- wait(): 객체에 대해 스레드를 대기하게 만듭니다.
- notify(): 객체에 대해 대기 중인 스레드가 있는 경우, 우선순위가 높은 스레드 하나만 깨웁니다.
- notifyAll(): 대기 중인 모든 스레드를 깨웁니다.
이벤트
- 이벤트는 대표적인 동기화 객체로 신호와 비신호라는 두 가지 상태를 가지며 코드 상에서는 Boolean값을 활용합니다.
- 특정 사건의 발생을 다른 스레드에 알리는 경우에 주로 사용합니다. 예를 들어 한 스레드가 작업을 완료한 후, 대기 중인 다른 스레드를 깨우는(호출하는) 경우가 있습니다. 즉, 한 스레드 종류 후, 다른 스레드로 시나리오를 진행할 때 이벤트를 이용합니다. 이벤트의 동기화 과정을 다음과 같습니다.
1. 이벤트를 비신호 상태로 생성한다.
2. 한 스레드가 작업을 진행하고, 나머지 스레드는 이벤트에 대해 Wait*()함수를 호출함으로써 이벤트가 신호 상태가 되기를 기다린다.
3. 스레드가 작업을 완료하면 이벤트를 신호상태로 바꾼다.
4. 기다리고 있던 모든 스레드가 깨어나서 작업을 진행한다.
'Developer's_til > 운영체제' 카테고리의 다른 글
프로세스의 스케줄링 (0) | 2021.11.08 |
---|---|
프로세스 제어 블록과 문맥 교환 (0) | 2021.11.08 |
[OS] 프로세스와 스레드의 특징 및 차이 (0) | 2021.05.18 |