지우너
[TIL] 2024.08.16 본문
코드트리 90xp
정보처리기사실기 강의
김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
프린트 하다가 잘못된 문서를 뽑을 경우 급하게 프린트를 멈춰야 하는 경우가 있다.
Queue(ConcurrentLinkedQueue)에 들어간 문자를 순서대로 출력하는 Runnable을 만든다.
main에서 입력받은 문자를 해당 스레드의 Queue에 넣어줌.
- 처음에는 volatile boolean work=true; 라는 변수를 만들어서 종료해야할 때 해당 플래그를 false로 바꿔줬다→반응성이 좋지 않음. 프린트가 된 다음 작업을 멈추게 됨
- interrupt()를 하면 즉시 작업을 멈춤. while에서 Thread.interrupted()체크를 하면 반응성을 높여줄 수 있음.
yield() 다른 스레드한테 cpu를 양보함.
- sleep을 해서 양보할 수도 있지만 RUNNABLE→TIMED_WAITTING→RUNNABLE로 상태 변화가 일어남 + 다른 스레드가 작업대기 중이라서 양보할 스레드가 없는데도 작업을 멈추는 문제가 있음.
- yield()를 하면 RUNNABLE(RUNNING)→RUNNABLE(READY)로 바뀌는 것이기 때문에 상태 변화가 일어나지 않음(자바는 두 상태를 모두 RUNNABLE로 동일하게 봄. 구분하지 않는다는 의미). 양보할 스레드가 없는 경우 자신의 스레드를 실행함.
Runnable에 flag변수 그냥 boolean으로 선언할 경우 생기는 문제.
flag변수는 메인 메모리에 올라가고. 스레드가 돌아갈 때 CPU의 작업속도를 위해 CPU 캐시 메모리로 복사된다.
스레드1에서 flag의 값을 바꿔도 이는 스레드1이 사용 중인 CPU 캐시 메모리에서 바뀌는 것이다.
flag를 사용 중인 스레드2는 이 값이 바뀌었는지 모른다는 의미.
스레드1이 바꾼 flag값이 CPU캐시 메모리에서 메인 메모리에 반영되어야 하고(언제 반영될지 모름)
메인 메모리에 바뀐 값이 스레드2가 사용 중인 CPU 캐시 메로리에 반영되어야(언제 반영될지 모름)
flag값에 따라 스레드2가 작업을 멈출 수 있다.
주로 바뀐 값은 컨텍스트 스위칭을 할 때 반영이 되지만, 반드시 갱신되는 것은 아니다.
스레드1에서 바꾼 값을 스레드2에서 바로 볼 수 있다면 이를 빠르게 반영할 수 있다. 이런 문제를 메모리 가시성 문제라고 한다.
메모리 가시성: 메모리에 변경한 값이 다른 스레드에서도 보이는지.
값을 이용할 때 메인 메모리에 직접 접근하면 메모리 가시성 문제를 해결할 수 있다(CPU 캐시 메모리에 접근할 때보다 성능은 떨어진다).
이를 제공해주는 키워드가 "volatile"(JAVA)이다.
'Records > TIL' 카테고리의 다른 글
[TIL] 2024.09.11 (0) | 2024.09.11 |
---|---|
[TIL] 2024.08.25 (0) | 2024.08.25 |
[TIL] 2024.08.17 (0) | 2024.08.17 |
[TIL] 2024.08.15 (0) | 2024.08.15 |
[TIL] 2024.08.14 (0) | 2024.08.14 |