먼저 GIL에 대해 알아보기 전에 파이썬 인터프리터에 대해 한 번 짚고 넘어가자.
인터프리터란 파이썬으로 작성된 코드를 한 줄씩 읽으며 실행하는 프로그램을 말하는데,
현재 파이썬 인터프리터의 표준 구현체로 받아들여지고 있는 것은 C언어를 이용하여 구현한 CPython이다.
GIL은 Global Interpreter Lock의 약자이다. 파이썬의 객체들에 대한 접근을 보호하는 일종의 뮤텍스(Mutex)로써, 여러 스레드가 동시에 파이썬 코드를 실행하지 못하도록 막는 것이다.
뮤텍스(Mutex)란, 멀티 스레딩 환경에서 여러 개의 스레드가 어떤 공유 자원에 접근하려 할 때 접근하기 위해 가지고 있어야 하는 키 같은 것이다. 식당에서 공용 화장실을 사용하기 위해 열쇠를 들고 화장실을 가고, 사용 중인 사람이 있을 때는 기다리는 것과 비슷하다고 이해하면 되겠다.
멀티스레드일 경우 Thread Context Switch에 따른 비용도 발생하기 때문에 오히려 싱글 스레드보다 시간이 오래 걸리는 문제가 발생한다.
그렇다면 파이썬에서는 왜 GIL이 필요한 것일까?
지난 포스팅을 참고하면, 파이썬에서의 각 객체는 reference count를 저장하기 위한 필드를 가지고 있고, GC는 reference count가 0이 되면 해당 객체를 메모리에서 삭제시키는 방식으로 동작하고 있다.
GC랑 GIL이 무슨 상관인 걸까? 참조 횟수에 기반하여 GC를 진행하는 파이썬의 특성상 Race Condition(하나의 값에 여러 스레드가 동시에 접근함으로써 값이 올바르지 않게 읽히거나 쓰일 수 있는 상태)이 발생할 수 있다.
즉, 각 객체의 reference count가 올바르게 관리되지 않을 수 있고, GC가 제대로 동작하지 않아 memory leak이 발생하거나, 반대로 메모리에 살아있어야 할 객체를 삭제시켜버리는 대참사가 일어날 수도 있는 것이다.
만약 GIL이 없다면, 스레드 간 공유하는 객체가 있을 경우 모든 객체에 대해서 참조되거나 참조 해제되는 경우에 대해 lock을 걸어야 하고, 정수 변수 하나까지 객체로 다루는 파이썬에서는 이러한 작업들이 매우 비효율적일 수밖에 없다.
그래서 그냥 인터프리터를 잠가버렸다.🔒
기본적으로 파이썬을 사용할 때 GIL로 인해 불편함을 느낄 가능성은 거의 없다고 봐도 된다.
단일 스레드일 경우 문제가 전혀 없고, CPU가 바쁘게 계산하는 일들은 GIL 바깥에서 효율적인 코드로 연산이 가능하며, 병렬 처리에 관해서는 굳이 스레드가 아니더라도 멀티프로세싱이나 asyncio 등의 많은 선택지가 있다.
또한, I/O 작업으로 인한 blocking이 발생하는 경우 그 시간 동안 다른 스레드에 실행 점유권을 넘겨줌으로써 더 효율적인 프로세싱이 가능해진다. 따라서, 네트워크 같은 입출력이 많은 작업(IO Bound)에 멀티 스레드를 사용하는 것이 적합하다.
파이썬에서는 GIL이 존재하기 때문에 GIL이 스레드의 안정성을 보장해줄 것이라고 생각할 수 있다. 스레드의 안정성이란 멀티 스레딩 환경에서 일반적으로 어떤 함수나 변수, 또는 객체가 여러 스레드로부터 동시에 접근이 이루어지더라도, 프로그램 실행에 문제가 없음을 뜻한다. GIL이 스레드의 안정성을 보장해줄까?
실제로는 아닐 수도 있다. 파이썬의 스레드는 한 번에 하나만 실행되지만, 파이썬 인터프리터는 실행되는 모든 스레드를 공평하게 취급하여 각 스레드의 실행시간을 균등하게 만들려 하고, 이를 위해 실행 중인 스레드를 일시 중단시키고 다른 스레드로 context switching을 반복한다. 이러한 과정에서 여러 개의 스레드가 같은 객체에 동시에 접근하는 것을 막지 못하며, 스레드끼리 언제 인터럽트 될지도 알 수 없다.
파이썬의 GIL에 대해서 듣기만 하다 한번 정리하는 시간을 가지니, 조금 더 명확하게 이해할 수 있었던 것 같다.
https://it-eldorado.tistory.com/160
https://dgkim5360.tistory.com/entry/understanding-the-global-interpreter-lock-of-cpython
https://thrillfighter.tistory.com/621
https://velog.io/@doondoony/Python-GIL
'🐍Python | Django' 카테고리의 다른 글
[Python] generator (0) | 2022.05.09 |
---|---|
[Python] iterable? iterator? (0) | 2022.05.08 |
[Python] Python의 메모리 관리 (0) | 2022.05.03 |
[Django] Django MTV (0) | 2022.04.29 |
[Python] call by value? call by reference? (0) | 2022.04.28 |