본문 바로가기
츄Log/끄적끄적

동시성 예제를 통해 보는 좀비스레드가 있을 때와 없을 때 차이

by 츄츄🦭 2024. 6. 16.
728x90

 

뇌가 뜨거워지는 어쩌고에서 작성한 것처럼, 

여러 스레드가 비동시성 컬렉션에 액세스하여 변경을 시도하면 경쟁상태가 발생하게 됩니다.

 

마치 앱이 중단된 것처럼 보이지만 내부적으로는 굉장히 열일을 하고 있는 것이죠.

 

CPU리소스는 쓰고 있으나, GC activity는 0입니다. (즉 GC에 사용되는 CPU 사용량은 없다는건, GC가 안되고 있다는 뜻 더 나아가 할 게 없다는 뜻이기도 합니다) 

일반적으로 동시성 문제로 발생하는 좀비 스레드를 나타내는 이상징후로 볼 수 있다고 합니다.

오히려 CPU 사용량에 GC에 의해 사용되는 비율이 월등히 높다면 메모리 누수 징후일지도 모릅니다.

 

어쨌든, 앱이 처리능력은 사용하고 있는데, 실제로 아무것도 처리하고 있지 않는 것입니다. 

또한 우측의 메모리 사용량도 보면 거의 사용하고 있지 않습니다. 즉, 앱이 아무것도 하고 있지 않다는 것을 의미하겠지요.

 

두 위젯이 가리키는 것은 조합해서 추론하면 동시성 문제의 근원일 가능성이 높습니다. 

이제 스레드 탭을 보겠습니다.

 

아무런 일도 하고 있지 않은 앱인데, producer1이 계속 Runnable 상태로 남아있습니다.

producer1 스레드를 사용하는 코드를 살펴보니 동시성 이슈로 while(true)구문에 의해 busy waiting을 하고 있는 것을 발견할 수 있습니다.

 


이제, 동시성이 고려되지 않은 Collection을 사용하는 코드에 synchronized 블럭을 통해 동기화를 해준 결과를 보겠습니다.

 

오.. 많이 다릅니다.

왜 CPU usage가 왜 -608.3%을 가리키는지는 모르겠습니다;;

 

하여튼, 직전에는 busy waiting을 하여 CPU 사용량이 12.6%였는데, 이제 8%로 떨어졌습니다. 

또한 우측 메모리 사용량도 다릅니다.

이번에는 정상적으로 일을 하고 있기 때문에 메모리를 사용하고 있습니다. (글로벌 큐에 발생/소비 하기 때문에 메모리 사용량이 위아래로 왔다갔다 하는 모습입니다)

 

GC usage는 0%인데, GC도 돌면 지표가 어떤 모습인지 확인해볼까요? 일단 하던거 하고 마지막에 봐보겠습니다.

 

스레드 탭을 보겠습니다.

오호 드디어 producer1, consumer1,2 모두 눈에 보이네요.

 

누구도 죽지 않고 살아있고 또 좀비로서 남아있지도 않습니다.

아까 동시성 이슈가 발생했던 스레드 결과는 consumer1,2는 죽어버리고 producer는 좀비로 살아있었죠 (차라리 예외터지고 죽는게 나은거같네요)

또한 synchronized 블럭으로 인해 thread상태가 BLOCKED가 되는 파란색 구간도 눈에 띕니다.

BLOCKED -> RUNNABLE -> ... 반복합니다.

 

스레드 비쥬얼라이제이션 색깔은 아래를 참고해주세요.

 

 

아까 이야기한 GC가 돌았을 때 그래프는 어떤 모양일지 확인하기 위해 producer를 많이 추가해보겠습니다.

참조하지 않는 객체를 무한으로 만들어보았습니다.

GC가 조금씩 동작하고, 그 순간순간 메모리가 정리되는 것 같습니다. 

 

좀 더 단순한 코드를 만들고, VM옵션을 통해 힙사이즈를 낮추고 다시 해보았습니다.

(vm option : -Xms100m -Xmx100m) 

 

임시 객체를 무한으로 생성하기만 해서, 메모리는 똑 떨어졌으면 GC가 발생한 것인데 

GC activity는 0.0%네요.

 

계산 방식이 제가 기대한 것과 다를 수도 있고, Minor GC여서 매우 짧을 수도 있고요

majorGC를 발생시켜보면 좀 더 비교가 될 것 같은데, 만드는게 쉽지 않네요.

 

지금 삼천포에 빠진 느낌이 좀 들어서, 이 작업은 다음에 각잡고 다시 파보겠습니다.

728x90