공유자원 A 을 사용하는 두 스레드가 있을 때,
A 의 값은 CPU 의 캐시영역과 RAM 영역에 모두 존재할 수 있다.
Thread1 의 A 에 대한 연산 결과가 CPU 캐시 메모리 존재할 시점에 Thread2 는 Thread1 의 쓰기 결과 값을 RAM 메모리에서 볼 수 없다.
이런 경우를 해결하는 것을 가시성이라한다.
협력적으로 실행되는 프로세스들이 마구잡이로 동시에 실행해서는 안 된다. 올바른 실행을 위해서는 동기화가 필요한데, 동기화란 특정 자원에 접근할 때 한 개의 프로세스만 접근하게 하거나 프로세스를 올바를 순서대로 실행하게 하는 것을 의미한다.
뮤텍스 락
acquire(){
while(lock == true);
lock = true;
}
release(){
lock = false;
}
acquire();
// 임계 구역
release();
세마포 & 모니터 : N 개의 프로세스 또는 스레드가 공유 자원에 접근할 때 상호 배제를 위한 동기화 장치
세마포
임계 구역에 진입할 수 있는 프로세스의 개수 혹은 사용 가능한 공유자원 개수를 나타내는 전역 변수 S
wait 신호를 보내는 함수 wait
wait(){
while(S <= 0);
S--;
}
사용 가능한 자원 S 가 있는지 반복적으로 확인한다.
가용 가능한 자원이 있으면 S 카운트를 감소하고 임계 구역에 진입한다.
임계 구역에 들어가도 좋다는 신호를 보내는 함수 signal
```java
signal(){
S++;
}
```
임계 구역에서 작업이 끝나면 S 를 1 증가시킨다.
wait();
// 임계 구역
signal();
뮤텍스 락 & 세마포어 차이
모니터
세마포는 임계구역 앞뒤로 일일이 wait 과 signal 함수를 명시하는 것은 번거로운 일이며
함수 누락이다 순서가 잘못 될 경우 문제가 발생할 수 있다.
그래서 세마포에서 진보된 동기화 도구가 모니터이다.
synchronized
volatile
이 키워드를 적용한 변수는 L1, L2 등에 캐시를 참조하지 않고 직접 메모리를 참조하도록 한다.
하지만 스레드 간의 동시 접근 동기화 문제는 synchronized
키워드로 해결해야 한다.
jdk 1.5 부터 멀티스레드 프로그래밍을 더욱 편리하게 지원하는 java.util.concurrent 가 도입됨
핵심 요소
락, 세마포어
atomics
원자성이란 더이상 쪼갤 수 없는 성질을 말한다.
이 개념을 CS 에 적용하면 완전하게 실행되거나 그렇지 않다면 아예 실행될 수 없는 것을 말한다.
원자성을 가지는 작업은 실행중에 종료되거나 중간에서 멈추지 않아야 한다.
cnt += 1;
코드는 한 줄이지만 컴파일 해보면 여러 명령어로 분해된다.
변수 cnt 에서 읽는 GETFIELD 와 쓰는 PUTFIELD 사이에 두 개의 명령어가 있다.
ICONST_1 에 진입한 스레드에 interrupt 가 걸리며 작업이 중단이 되고,
그 사이에 다른 스레드가 add() 메서드 작업을 수행해 cnt 값을 변경하면 두 스레드간 동기화가 깨지게 된다.
cnt += 1;
코드는 원자성이 보장되지 않는 작업이다.
synchronized
키워드로 해결할 수 있지만 jdk1.5 부터 Atomic 클래스가 도입되었다.
블로킹 큐
래치
executor