| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 쿠버네티스
- 스프링 부트
- Web
- JdbcTemplate
- 컨테이너
- JPA
- Routing Key
- 지연 로딩
- docker
- dockerhub
- Dead Letter Queue
- mybatis
- redis
- CORS
- kafka
- @ComponentScan
- docker compose
- 페이징
- JWT
- DI
- MSA
- Spring Container
- JPQL
- Spring
- AWS
- 서블릿 컨테이너
- DLQ
- @Transactional
- Spring Data JPA
- securitycontextholderfilter
- Today
- Total
look-forest
Java의 동기화 문제 해결 본문
자바 동기화를 위한 synchronized 키워드, wait(), notify 메소드에 대해 알아보겠다.
특히 Java는 Monitor를 제공한다.
Monitor는 모니터 내부에서는 항상 하나의 프로세스만이 활성화되도록 보장해 주므로, 프로그래머 가 동기화 제약 조건을 명시적으로 프로그래밍해야 할 필요가 없다는 장점이 있다.
자바에서 모든 객체는 monitor를 가지고 있고, monitor는 여러 스레드가 동시에 객체로 접근하는 것을 막는다.
스레드가 monitor를 가지면, monitor를 가지는 객체에 lock을 걸어 다른 thread들이 해당 객체에 접근할 수 없게 한다.
monitor를 가질 수 있는 것은 synchronized 키워드 내에서 가능하다.
synchronized
임계 영역에 해당하는 코드 블록을 선언할 때 사용하는 자바 키워드
임계 영역을 지정만 하면 lock 획득, 반납은 Java가 알아서 해준다!!
- 해당 코드 블록(임계 영역)에는 모니터락을 획득해야 진입 가능
- 모니터락을 가진 객체 인스턴스를 지정할 수 있음
- 메소드에 선언하면 메소드 코드 블록 전체가 임계 영역으로 지정되고, 모니터락을 가진 객체 인스턴스는 this가 됨

사용 사례


object가 synchronized에 파라미터로 들어가면서, thread가 object의 모니터 락을 가질 수 있게 된다.
여기서 쓰인 object 객체는 단지 모니터 락을 획득하기 위해 필요할 뿐이다.
모니터는 임계영역에서 뭘 하는진 상관없고, 그저 한번에 하나만 접근하게 보장한다. 공유 데이터에 대한 문제가 아니다.
주의할 점



wait() and notify()
순서를 배정해주려면 wait()와 notify()가 필요하다.
- java.lang.Object 클래스에 선언되어, 모든 자바 객체가 가진 메소드이다.
- 스레드가 어떤 객체의 wait() 메소드를 호출하면, 해당 객체의 모니터락을 획득하기 위해 대기 상태로 진입한다.
- 스레드가 어떤 객체의 notify() 메소드를 호출하면, 해당 객체 모니터에 대기 중인 스레드 하나를 깨운다
(notifyAll()은 해당 객체 모니터에 대기 중인 스레드를 전부 깨운다)
모니터 락으로 구현했기 때문에 간단하다.
세마포어: c의 sem_wait, sem_post
empty니 full이니 헷갈리고 복잡하다.
pthread_mutex_t mutex;
sem_t empty, full;
void insert_item(int item) {
sem_wait(&empty);
pthread_mutex_lock(&mutex);
/* 임계 구역 */
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
모니터: Java의 wait(), notify()
wait(empty), notify(full)이 아니라 헷갈릴게 없다!
/* 모니터 락 사용. 하나의 스레드만 들어오도록 보장 */
synchronized public void give(int money) {
while (count == buffer.length) { //버퍼가 다 찼으면 대기한다.
try {
wait(); //바쁜 대기를 하는게 아니라 consumer가 notify해주길 기다린다.
} catch (InterruptedException e) { //wait하다가 notify() 호출되면 인터럽트 걸려서 탈출한다.
}
}
/* 임계 구역 */
notify();
}
monitor의 라이프사이클은 synchronized 키워드에 의존한다.
그래서 객체가 가지는 wait(), notify(), notifyAll() 메소드는 모두 synchronized 블록에서만 유의미하다.
해당 메소드들로 스레드를 waitset에 넣거나, waitset에서 부터 불러 올 수 있게 된다.
참고 자료 & 이미지 출처
운영체제 공룡책 강의 (주니온 님)
Operating System Concepts, 10th Ed (Silberschatz et al)
쉽게 배우는 운영체제 (조성호 님)
'Computer Science > Operating System' 카테고리의 다른 글
| Deadlock (0) | 2021.06.12 |
|---|---|
| 동기화 문제의 사례들 (0) | 2021.06.11 |
| 임계 구역 문제 솔루션: OS, Language supported SW solution (0) | 2021.06.09 |
| 임계 구역 문제 솔루션: SW solution, HW solution (0) | 2021.06.09 |
| Critical Section Problem: 프로세스 동기화가 필요한 상황 (0) | 2021.06.09 |