Lock 구현 이론

CJB_ny·2022년 2월 13일
0

Unity_Server

목록 보기
12/55
post-thumbnail

지난시간 까지 락에 대한 설명을 하였고

데드락까지도 설명을 하였는데

1. Lock 동작 이해하기

사실은

"멀티 쓰레드"프로그래밍에서

"Lock"의 비중이 한

60%~70% 정도는 될 정도로 굉장히 중요하게 사용이 된다.

그렇기 때문에

Lock은 도대체 어떻게 동작을 하는지

대략적으로 나마 이해를 하는 것이 굉장히 중요하다.

그런데 이것이 언어마다 프레임 워크마다 구현방법이 조금씩 다르다.

그런데, 어떤 철학으로 구현이 되어있는지는 당연히 알아야 하니까

오늘은, 그거에 대해서 알아볼 것이다.

그래서 코드를 보기전에 "식당"스토리로 가서 개념 이해를 함 해보자.

이런 상황에서 할수 있는 방법이 첫번째로

그냥 무작정 기다리는 방법이 있을 것이다.

그런데 영영 안나오거나 정말 오래 걸린다면..??

그다음 두번째 방법은

이런식으로 자기 자리로 다시 돌아가 랜덤시간동안 자기 자리에 있다가

(예를들어 5분정도 있다가)

화장실에 가보는 것이다.

만약 운이 좋으면 화장실을 쓸 수 있는 것이고

화장실에 누군가가 있어서 자리로 다 돌아왔는데 그때 화장실에서 볼일을 다 보고 나올 수도 있고

아니면 내가 자리로 간사이 화장실을 다쓰고 나왔는데 다른 누군가가 와서 사용을 한다거나

그런 문제점이 있다.

갑질 메타도 있는데

직원에게 부탁을해서 나는 자리에서 영화를 보고있을테니

화장실을 누군가 다 사용하고나면 나에게 알려달라! 라고 부탁하는 것이다.

이렇게하면 나는 편하지만 직원은 안좋은? 부담이 되는 상황이다.

누군가를 거쳐서 하게되니까

만약 100명이 동시에 이런 부탁을 한다면 직원 입장에서는 짜증나는 상황이 될 것이다.

그래서 아무튼 이렇게 현실세계에서 일어 날법한 일들을 설명을 해보았는데

락 구현에서도 이렇게 비슷하게 일들이 일어난다.

우리가 락을 구현을 할때 이미 누군가가 락을 차지를 하고있을때

어떻게처리를 할지가 사실 굉장히 핵심적인 부분이고

어떻게 처리를 하는지에 따라서 "성능"이 왔다 갔다 할텐데

첫번째 경우

2. 첫번재 방법 Spin Lock

이 경우

무작정 기다리는 것이 "Spin Lock"의 개념이다.

그냥 무작정 기다리다가 나오면 그 자리를 차지를 할 수 있겠지만

만약에

오랬동안 안 나온다고 가정을 하면은

뺑뺑이를 돌면서 기다리고있던애는 굉장히 허탕을 치게되는 그런 상황이다.

그리고 저렇게 그냥 기다리는게 우리 입장에서는

"멍" 때리는 거일 수도 있지만

컴퓨터 입장에서는 기다리는 애(녀석)한테 영혼을 빙의 해가지고 쓰레드를 계속 실행시키고 있는 상황인 것이다.

그러니까 우리가 생각하는 것처럼 멍때리는 것도 그렇게 가벼운 작업이 아니다.

그래서 나중에 spinLock을 구현을 해볼것인데

스핀락을 구현해서 계속 뺑뺑이를 돌게 하고있는데

만약에 화장실에 있는 애가 안나오면,

그때, 일어나는 현상은 CPU점유율이 튀게 된다!

왜냐하면 계속 무한 루프를 돌면서 기다리는 작업을 계속 하고있기 때문에

계속 체크를 하는것이다 -> 비었나? 비었나? 비었나? 비었나?? ... 이런식으로

그래서 CPU가 점유율이 확튀는 그런 상황이 발생을 하는 것이다.

3. 두번째 방법

그리고 두번째 방법은 무어냐 하면은

이방법은 그냥

쓰레드가 자기의 소유권을 그냥 포기를 하는 것이다.

이게 Thread.Sleep(0); 을 해도되고 yield를 해도되는데


Thread.Sleep, yield뭔지 질문


어쨋든, 자신의 소유권을 포기를 하고 어느정도 시간 있다가 다시 나를 실행시켜줘!

라는 느낌으로 하는 것인데,

우리가 사실은 쓰레드에 대한 얘기를 하면서

CPU Core가 직원(쓰레드)를 실행시킨다고 했었다.

그리고 Thread를 무작정 무한대로 실행시키는 것이 아니라,

어느 정도 실행을 할지 시간을 분배를 해가지고

"너는 0.1초동안 움직일 수 있어!"라고 시간을 줄 것이다.

그러면 그 시간을 대충 다 썻으면은 이제 회수 해가지고(영혼을)

다른 애를 움직이게 하거나 그러는 것인데

여기서 일단 자리로 돌아간다는 의미가 무엇이냐 하면은

그냥 소유권을 포기한다는 것이다.

그러니까, 0.1초 시간을 줬는데 굳이 0.1초 시간을 다 사용하지 않더라도,

딱봐도 지금 화장실을 누군가가 사용을 하고 있고, 할게 없다고 판단이 되니까

그냥 자기 소유권(영혼을) 돌려주는 것이다.

그러니까 이제 CPU Core는 저 오른쪽 쓰레드를 실행하는 시간을 돌려받았으니까,

그시간에 이제 다른 애를 실행을 하러 가게 된다는 말이다.

그런데 아까 첫번째 방법 == 무작정 기다리는 방법보다는

두번째 방법은 이렇게 왔다 갔다 하는 이 거리가 있을 것이다.

그게 이제 나중에 "Context Switching"이라는 개념에 대해서 살펴 볼것인데

이런식으로(두번재 방법처럼) 자신의 소유권을 놔줘가지고

쓰레드가 다른애를 실행시키러(빙의하러) 이제 옮겨 다닐텐데

그렇게 옮겨 다니는 작업이 생각보다 부담이 엄청 크다.

그래서 두번째 방법은 시간? 적인 부담이 조금 있다.

그래서 이제 마지막 세번째 방법에 대해서 살펴보자

4. 세번째 방법

이 방법은 Event라는 방법을 사용을 해가지고

역으로 통보를 받게되는 방법이다.

그래서 "(2) I will be back (소유권 양도)" 하는 방법 까지는 비슷하다.

그런데, 이제 랜덤으로 나중에 대충 깨는 것이 아니라

일단은 "Kernel"에다가(직원) 운영체제에다가 부탁을 하는 것이다.

어떤 Event를 setting 해가지고

화장실의 자물쇠가 비면은

Event를 발생시켜달라는 "예약"을 해둘 것이고

만약에 화장실의 자물쇠가 딱 풀려가지고

운영체제 차원에서 Event를 뿅!하고 발생시키면은

오른쪽(기다리는 사람) 쓰레드는 얼씨구나 하고 (4) 통보후 => 화장실로 갈 것이다.

그러니까 아까 이전에 왓다갓다 하는 것 까지는 비슷한데

"깨어나는" 시점이 조금 다르다.

무작정 자기 차례가 올때까지 기다리는 것이 아니라

조금더 스마트하게 운영체제 한테 부탁을 해가지고

화장실이 비어있다면 Event를 호출 하게끄름 하는 방법이다.

그래서 이렇게 세가지 방법이 있다는 것을 알아 보았다.

그래서 이제 이것들을 구현읋 해보면서

Lock에대한 이해도도 높이고

멀티쓰레드에 대한 코딩도 해볼겸

이것들을 구현을 해보도록 하자.

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글