파이썬 쓰레드 사용시 주의할 점
파이썬에서는 쓰레드(Thread)를 이용하여 병렬 처리를 할 수 있습니다. 하지만 쓰레드를 잘못 사용하면 예상치 못한 오류가 발생할 수 있습니다. 이번에는 파이썬의 쓰레드 사용시 주의할 점에 대해 알아보겠습니다.
쓰레드와 GIL
파이썬의 쓰레드는 GIL(Global Interpreter Lock)이라는 뮤텍스에 의해 제어됩니다. 이 뮤텍스는 매 순간 하나의 쓰레드만이 파이썬 인터프리터를 제어할 수 있도록 합니다. GIL 때문에 파이썬에서 멀티 프로세싱을 할 경우 GIL이 공유되지 않기 때문에 실제 멀티 코어 CPU에서 병렬처리를 할 수 없습니다. 하지만 멀티 스레딩은 가능합니다. 하지만 쓰레드 만큼 빠르게 돌아가지 않는 이유가 있습니다.
파이썬의 메모리 관리
파이썬은 메모리 관리를 자동으로 수행합니다. 객체의 레퍼런스 카운트(Reference Count)가 0 이되면 GC(Garbage Collector)가 그 객체를 처리합니다. 하지만 이 과정에서 뮤텍스가 사용되며, 많은 쓰레드가 동시에 GC를 실행할 경우 성능 저하나 데드락(Deadlock)이 발생할 수 있습니다. 파이썬에서는 이러한 이유로 GC를 멀티 쓰레드에서는 사용하지 않습니다.
쓰레드 기능 사용 예제
쓰레드 상호작용을 위해서는 threading
모듈을 이용할 수 있습니다. 아래와 같이 예제 코드를 작성해보겠습니다.
“`python
import threading
def worker():
print(‘start worker’)
print(‘end worker’)
def main():
print(‘start main’)
thread = threading.Thread(target=worker)
thread.start()
print(‘end main’)
if name == ‘main‘:
main()
“`
위 예제 코드는 쓰레드를 이용하여 worker
함수를 실행하는 코드입니다. threading.Thread
를 이용하여 새로운 쓰레드를 생성하고, 쓰레드를 시작할 때는 start()
함수를 호출합니다. start()
함수가 호출되면 생성한 쓰레드가 실행됩니다.
쓰레드 사용시 주의할 점
-
GIL 때문에 동시에 여러 개의 쓰레드가 CPU를 공유하는 것은 불가능합니다. 따라서 코어 수보다 많은 쓰레드를 생성하더라도 성능이 나빠질 뿐입니다.
-
파이썬에서는 GC를 멀티 쓰레드에서 사용하지 않으므로, 메모리 누수가 발생하지 않도록 주의해야합니다. 예를 들어, 쓰레드에서 객체를 생성하고 외부에서는 그 객체를 사용하는 경우, 쓰레드의 수명이 끝났을 때 객체에 대한 레퍼런스 카운트가 0으로 감소하지 않아 메모리 누수가 발생합니다. 이러한 경우 쓰레드 풀(Thread Pool)을 이용하여 객체 생성을 제한할 수 있습니다.
-
쓰레드에서는 예외가 발생하면 쓰레드 자체가 종료될 수 있습니다. 따라서 쓰레드 작업 내부에서 예외 처리를 꼭 해주어야 합니다.
-
적절한 동기화(Synchronization) 미사용으로 인한 경쟁상태(Race Condition) 문제가 발생할 수 있습니다. 리소스에 대한 접근은 최소한으로 제한하고, 적절한 동기화 기술을 사용하여 프로그래밍 하도록 합니다.
결론
파이썬의 쓰레드 사용에 대한 예제와 함께 불필요한 오류 발생을 줄이기 위한 주의점을 살펴보았습니다. 이러한 주의사항을 준수하면 비록 GIL 때문에 파이썬에서 멀티 코어 CPU를 이용한 병렬 처리는 불가능하지만 적절한 쓰레드 사용으로 병렬 처리를 할 수 있습니다. 하지만 성능 측면에서 꼭 필요한 상황이 아니면 멀티 프로세싱을 이용하여 작업하는 것이 좋습니다.