GIL은 Global Interpreter Lock의 줄임말이다.
이것의 정체는 정확히는 '뮤텍스'이다. 이 뮤텍스는 한번에 오직 하나의 스레드만이 파이썬 인터프리터에 대한 control을 할 수 있게 제한한다.
즉, 진정한 의미의 멀티스레딩이 불가하다는 것이다.
공식 파이썬 implementation은 CPython이다.
이 CPython은 Garbage Collection을 수행할 때, Reference Count(RC)를 본다.
파이썬에서 모든 데이터는 객체이며 각 객체는 변수에 의해서 참조된다.
예를 들어 아래 코드를 보자
a = [1, 2, 3] # 1
b = a # 2
[1, 2, 3]객체는 변수 a에 의해 참조된다. 여기서 RC는 1이다.
[1, 2, 3] 객체는 이제 변수 'b'에 의해서도 참조된다. 이제 RC는 2가 된다.
그럼 Garbage Collect가 일어나도록 해보자.
a = [1, 2, 3]
b = a
a = 'a' # 3
b = 'b' # 4
변수 a가 str 객체 a를 참조하게 되면서 [1, 2, 3]의 RC는 1로 줄어든다.
변수 b 또한 str 객체 b를 참조하게 되면서 [1, 2, 3]의 RC는 0이 된다. 이제 [1, 2, 3]은 언제든지 GC가 될 수 있다.
OS를 공부하신 분이라면 모두 들어봤을 멀티스레딩의 critical section을 생각해 봐야 한다.
RC의 값을 변경하는 것이 바로 Critical Section이 된다. 여러개의 스레드가 동일한 객체를 참조한다고 해보자. 당연히 이 값을 업데이트 하는데 문제가 있을 것 같다는 생각이 든다.
CPython에서는 이 문제를 해소하기 위해 GIL을 사용하는 것이다. 결론적으로 보면 GC를 제대로 하기 위해서 GIL을 사용하는 것이다.
앞에서도 말했듯이 우리가 원하는 진정한 멀티스레딩(여러개의 코어에서 각각 스레드가 돌아가는)을 구현하려면 GIL은 당연히 문제가 된다.
특히 CPU-bounded 한 task를 수행하는데 성능에 큰 지장을 준다. 이때문에 이를 과도한 통제라고 하는 시각도 적지 않다.
하지만 파이썬을 사용한다고 무조건 GIL을 사용해야 하는 것은 아니다. Jython이나 IronPython 같은 파이썬 구현체는 GIL을 사용하지 않음으로써 멀티스레딩을 구현할 수 있도록 한다.
성능적으로 이슈가 많다는 것을 당연히 파이썬재단에서도 알고 있다. 그래서 그런지 파이썬 3.13이 올해 release하면서 GIL을 선택적으로 사용할 수 있도록 해주는 experimental feature가 추가되었다.
멀리 내다보았을 때 아무래도 싱글스레드를 고집할 수 없기 때문에 GIL은 언젠가는 사라질 듯 하다.