- 공유 자원: 여러 스레드가 동시에 접근할 수 있는 자원
- 임계 영역: 공유 자원들 중 여러 스레드가 동시에 접근했을 때 문제가 생길 수 있는 부분
이 때, 생길 수 있는 문제가 경쟁상태- 경쟁상태: 둘 이상의 스레드가 공유 자원을 병행적으로 읽거나 쓰는 동작을 할 때 타이밍이나 접근 순서에 따라 실행 결과가 달라지는 상황
Ex) Read - Modify - Write, Check - then - act
만약 동시에 30명이 수강 신청한다면
- 테스트 결과 28명으로 나온다. 왜 그럴까
- 스레드가 맞물렸기 때문!
- 왜 80대의 숫자가 찍힐까
- studentCount가 28인걸로 가정하고 아래 타임라인을 살펴보면
if 분기문 통과 시점에 다른 스레드에서 studentCount + 1을 수행하여 경쟁상태가 발생한다.
✅ 이러한 경쟁상태를 방지하기 위해서 원자성과 가시성을 보장해야 한다.
: 공유 자원에 대한 작업의 단위가 더 이상 쪼갤 수 없는 하나의 연산인 것처럼 동작하는 것
- 미사일이 날아오면 요격하는 시스템
- 2개의 스레드 존재
- 미사일 감지하여 MissileLaunched를 true로 바꾼다.
- MissileLaunched가 true가 되면 요격 미사일 발사한다.
- 5초 후에 missileLaunched를 true로 바꾼다.
- 그럼 5초 후 요격 메세지가 출력되어야 하지만 2분이 넘도록 요격이 출력되지 않는다.
가시성을 이해하기 위해서는 CPU Cache에 대해 이해해야 한다.
스레드가 실행하면 CPU를 실행한다.
스레드가 CPU를 실행할 때 Main memory에서 변수 값을 읽어와 스레드를 실행한다.
그런데 Main memory와 CPU 사이에 거리가 멀어 CPU Cache를 사용한다.
CPU는 스레드를 실행할 때 필요한 값을 Main memory에서 읽어와서 CPU Cache에 담아두고 CPU Cache의 모든 연산을 반영한 다음에 그 값을 Main memory에 덮어쓰는 방식으로 동작을 한다.
요격하는 스레드는 CPU Cache에 담긴 false라는 값을 계속 보고 있어서 2분이 넘도록 요격이 출력되지 않았다.
- Main memory에서만 값을 읽고 쓰고 CPU Cache를 사용하지 않는다.
정상적으로 값이 출력된다.
- 원자성과 가시성을 챙기는 것을 동기화라고 한다.
- 특정 스레드가 적업을 수행한느 동안 다른 작업은 진행하지 않고 대기하는 방식
Ex) Monitor, Synchroized 키워드
- Java에서 동기화를 하기 위한 도구
- 배타동기는 synchroized, 조건동기는 wait(), notify(), notifyAll()
- 임계영역에 하나의 한 번에 하나의 스레드만 락을 가지고 들어가도록 설계되어 있다.
만약 하나가 작업을 하다가 wait() 연산을 만나면 해당 스레드는 슬립 상태가 되면서 조건동기 큐로 간다.
그리고 대기 중이던 배타동기 큐에 있는 다른 스레드가 임계 영역으로 들어간다.
만약 notify() 또는 notifyAll()을 호출하면 슬립 상태의 스레드를 깨워서 임계 영역이 비웠을 때 작업을 수행하도록 한다.
- 배타동기를 선언하는 키워드
- 연산결과가 메모리에 써질 때까지 다른 스레드는 대기
- 순차 접근하여 원자성 + 가시성 보장
- 단점
- 대기로 인한 성능 저하
- 락을 가지고 임계 구역에 들어가기 때문에 DeadLock 발생 가능
가지고 있는 자원을 놓지 않고 상대방의 자원을 기다리는 상태를 데드락이라 한다.
예시)
- 옷이 한 벌만 존재
- 하나씩 입고 있는 상태에서 자신의 옷은 벗지 않고 상대방이 옷을 벗기를 서로 기다리고 있는 상태
- 데드락이 걸린 상태로 10초 이후에 테스트가 종료된다.
만약 데드락이 걸리지 않았다면 예외를 발생시켜 테스트기 실패한다.
- 다른 스레드의 작업 여부와 상관없이 자신의 작업을 수행하는 방식
Ex) Atomic 타입
- 동시성을 보장하기 위해 Java에서 제공하는 Wrapper class
- CAS + Volatile
30번 요청 시 (앞서 나왔던 28번이 아닌) 정상적으로 30번이 나온다.
여러 스레드가 동시에 클래스를 사용하려 하는 상황에서 클래스 내부의 값을 안정적인 상태로 유지할 수 있다.