면접 질문들을 모아놓은 레포를 보다 보면, 싱글톤 패턴은 많이 언급한다는 것을 알 수 있습니다. 거기서 DCL 패턴이 나오고, volatile도 나오는데요. 여기서 volatile이 무엇을 의미할까요?
먼저, 간단하게 프로그램을 작성해 보겠습니다. Main 스레드와 Worker1 스레드 하나가 있습니다. 이 프로그램은, Main Thread에서 w1의 stop flag를 중간에 true로 셋팅합니다.
Worker1의 run 메소드는 그냥 stop flag가 false이면 계속 돕니다. 결과가 어떻게 나올까요?
공교롭게도, 0 : stop flag만 출력하고 더 이상 진행되지 않습니다. 이는 왜 그럴까요? 공식 문서를 보면 자세히 알 수 있습니다.
Note 바로 윗 단락의 내용을 천천히 봅시다. 일단, while loop가 도는 동안에 stop flag는 자주 접근이 되는 대상이였습니다. 그렇기에, 컴파일러는 register에 stop flag를 넣을 수 있습니다. 이 상황을 그림으로 그려 봅시다.
레지스터에 stop을 올렸다. 그런데, 그 다음에 이런 문장이 나옵니다. 매번 테스트를 할 때 마다 메모리에 있는 변수에 접근하지 않는다. 이건 또 무슨 말일까요? memory hierarchy나 register speed라는 키워드로 검색을 해 보시면 많이 보이는 그림은, register가 맨 위에 있고, 다음에 cache, main memory가 있는 그림입니다. 이 포스팅을 설명하는 데 필요한 부분만 그리면 아래와 같습니다.
대략적으로 그려보면 위와 같습니다. Worker 스레드에 대해서, stop은 false였고, 컴파일러 최적화가 되었다면, 레지스터에 있는 stop도 false가 올라가 있을 겁니다. 그런데, 왜 메인 메모리에 접근하지 않을까요? 레지스터에 올려져 있기 때문입니다. 그리고 거기서 읽어들이는 게 효율적이기 때문입니다.
문제는, main에서 w1.stop을 바꾸었을 때입니다.
이 때에는 register에 올라간 stop 말고 다른 stop이 바뀌게 될 수도 있습니다. 예를 들자면 메인 메모리에 올라간 stop이라던지. 예를 들어서, 1번 코어가 worker1 thread를 수행하고, 2번 코어가 main thread를 수행한다고 해 봅시다. 그런데, 이미 worker1 스레드에 있는 stop을 읽어올 때, 레지스터에 있는 stop을 읽어올 거에요.
그런데, 사실 제가 노란색으로 친 부분은 main thread가 접근을 하지 못합니다. 이를 visible하지 않다고 합니다.
그러면, worker1 thread가 읽어오는 stop이 아닌, 다른 stop에 flag를 업데이트 할 겁니다. 중요한 것은, 이 경우에, worker 1에서 루프는 계속 돈다는 것입니다. 레지스터에 저장된 stop이 업데이트 되지 않았기 때문입니다.
그러면 어떻게 하면 될까요? volatile 키워드를 붙이면 됩니다.
아까와 다른 점은 stop에 volatile이 붙었다는 것입니다.
실행을 해 보면, 1000번 다 돌고 끝났음을 볼 수 있습니다. 이는 volatile이 최적화를 제외시켜서, 레지스터 대신 메모리에서 접근하게끔 했기 때문입니다. 그런데, 이것은 Thread safe와는 무관한 키워드임을 알 수 있습니다. 단지, 컴파일러의 최적화를 제한한 것일 뿐입니다. 테스트 프로그램을 돌려보면 알 수 있습니다.
Worker1에는 sum 변수가 들어 있습니다. Main에서도 Worker1에서도 접근 가능한 공유 변수입니다. Main 스레드에서는 공유변수를 10만번 1씩 감소시킵니다.
Worker1은 10만번 증가시킵니다.
실행 결과는 위와 같습니다. 이 결과는 volatile과 Thread safe, lock하고는 별개의 키워드임을 보여줍니다. 싱글톤 패턴할 때 한 번 더 언급이 될 듯 하니 알아두면 좋을 듯 싶습니다. 여담으로, 이것은 올해 4월에 스터디 한 건데 8개월이 지난 시점에 올리는 것을 보면 포스팅이 많이 밀리긴 했나 봅니다.
'OS > 이론' 카테고리의 다른 글
java future 에 대해서 간단하게 이해해 봅시다. (4) | 2021.04.01 |
---|---|
java arrayblockingqueue : 고정 크기를 가지는 생산자 소비자 문제에 써 봅시다. (2) | 2021.02.13 |
백준 k번째 소수 문제와 지역성의 원리 (0) | 2020.12.08 |
java notify 메서드와 deadlock (0) | 2020.11.24 |
왜 wait 메서드는 반복문 안에서 써야 할까요? (0) | 2020.11.14 |
최근댓글