1. 리팩토링 미션 4단계 제출
3단계 리뷰 답변하고, 4단계 pr 작성해서 제출 완~
2. 동기화, 경쟁조건, 임계영역
📍 동기화가 없으면 생기는 문제
하나의 객체에 두개의 스레드가 접근하면 생기는 일
메모리에서 이 프로그램을 돌리기 위해 할당받은 메모리 영역에서
그 안의 힙 영역에는 두 스레드가 모두 접근 가능한 badCounter 객체가 있다.
처음 상태는 state = 0
cpu는 싱글 코어라고 가정.
같은 프로세스에 속한 두 스레드 t1, t2
싱글 코어니까 멀티태스킹 방식 동작 -> 중간에 context switching 일어나서 t1, t2가 번갈아가며 cpu에서 실행
state++;가 cpu레벨에서 어떻게 동작?
프로그래밍언어를 cpu가 이해할 수 있는 언어로 변환
- 메모리에 있는 state 값을 cpu 속 register r1에 로드
- r1값에 1 더해서 다시 register에 저장
- register에 있는 값을 메모리에 저장
increment를 호출할 때 타이밍에 따라 다른 결과 나옴
만약 t1이 두번째 단계까지 했을 때 context switching이 일어나면..!
t2가 동작. 메모리에 있는 state값(현재0)을 register에 올림. 0+1. 1을 state에 저장 -> state=1
여기서 다시 context switching이 일어나 t1으로 돌아가면,
t1은 아까 멈춘 그 다음(세번째 단계)부터 실행. 이전에 실행한 마지막 단계가 r1=1이었으니 1을 state 저장 -> state=1
=> t1에서도 한번, t2에서도 한번 호출. 우리가 기대하는 값은 state=2인데, 결과는 state=1
=> 스레드에서 언제 context switching이 일어나느냐에 따라 결과가 달라질 수 있다
📍 경쟁조건 (race condition)
📍 동기화 (synchronization)
📍 어떻게 동기화 시킬 것인가?
프로그래밍언어 레벨에서는 단일 명령문 (state++)
cpu 레벨에서는 복합 명령문 (load~, r1~, store~)
실행 중간에 cs가 일어나 문제!
-> 실행되는 동안에는 context switching이 일어나지 않도록 하면 되겠다?
-> 이 방법은 single core에서는 가능. multi core에서는 불가
(multi core에서 두 cpu가 동시에 load state to r1해버리면 동일한 상황 발생)
=> increment를 실행할 때 이 메소드를 한번에 한 스레드만 들어갈 수 있게 하자!! (다른 스레드가 들어가있으면 기다리도록)
📍 임계 영역 (critical section)
critical section 관련 문제 : critical section problem
csp를 해결하기 위한 뼈대
cs에 진입하기 전에 entry section에서 cs에 진입할 수 있는지 요건 검사
-> cs에서 할일
-> 나올 때 exit section
mutual exclusion : 한번의 하나의 스레드만 critical section에서 실행할 수 있다
progress : 만약 critical section이 비어있고, 어떠한 스레드들이 cs 진입을 원한다면 그 중 하나는 cs안으로 들어갈 수 있도로 해야한다(진행이 계속 되어야 한다)
bounded waiting: 어떤 스레드가 cs에 들어가지 못하고 무한정 대기해서는 안된다
위 세가지를 모두 만족해야 critical section problem의 해결책이 될 수 있다
📍 Thread safe
위에서 본 counter 클래스는 thread safe하지 않다.
-> multi threading 상황에서 그냥 사용하면 race condition이 발생할 수 있다.
우리가 직접 개발하는 클래스 뿐만 아니라, 언어 레벨에서 제공하는 클래스에도 그런 이슈가 발생할 수 있다.
ex. 자바의 SimpleDateFormat. 읽어보면 동기화되지 않았다는 내용. 만약 여러 스레드가 이걸 공유해서 쓰려고 한다면, 외부에서 반드시 동기화를 시켜줘야한다.
-> 자바 기본 제공 클래스라고 무조건 쓰면 안된다. 문서 잘 읽어봐야한다.