이 글에서는 Python의 스레드(Thread) 개념부터 threading 모듈의 핵심 함수, 그리고 실제 예제 코드와 실행 결과까지 체계적으로 살펴봅니다.
스레드(Thread)란 무엇인가?
컴퓨터 과학에서 스레드(thread)는 운영체제(OS)의 핵심 구성 요소인 스케줄러(scheduler)가 독립적으로 관리할 수 있는 일련의 명령어 집합을 의미합니다.
스레딩(Threading)의 핵심 기능은 여러 스레드를 동시에 실행하는 것입니다. 여기서 스레드란 프로그램 내에서 수행되는 서로 다른 작업이나 함수 호출을 뜻하며, 여러 스레드가 동시에 실행된다고 해서 반드시 서로 다른 머신에서 실행되는 것은 아닙니다.
멀티스레딩이 필요한 두 가지 경우
멀티스레딩(multi-threading)은 주로 다음과 같은 상황에서 활용됩니다.
서브 프로그램(하위 프로그램)의 출력 결과를 메인 프로그램과 결합해야 할 때
메인 프로그램이 서로 비교적 독립적인 코드 조각들로 구성되어 있을 때
Threading 모듈
Python은 매우 강력한 threading 모듈을 제공하며, 이 모듈은 스레드에 대한 고수준(high-level) 지원을 담당합니다.
threading 모듈은 스레드 관련 데이터를 조회하는 데 사용되는 다양한 함수들을 정의하고 있으며, 이러한 함수들은 자동으로 실행됩니다.
주요 함수 살펴보기
threading.active_count()
현재 살아 있는(alive) Thread 객체의 개수를 반환합니다. 반환되는 값은 enumerate()가 반환한 리스트의 길이와 동일합니다.
threading.current_thread()
호출자의 스레드 제어 흐름에 해당하는 현재 Thread 객체를 반환합니다.
threading.get_ident()
현재 스레드의 '스레드 식별자(thread identifier)'를 반환합니다. 이 값은 0이 아닌 정수입니다.
threading.enumerate()
현재 살아 있는 모든 Thread 객체의 리스트를 반환합니다. 여기에는 데몬(daemon) 스레드, current_thread()가 생성한 더미(dummy) 스레드, 그리고 메인 스레드가 포함되며, 이미 종료된 스레드나 아직 시작되지 않은 스레드는 제외됩니다.
threading.main_thread()
메인(main) Thread 객체를 반환합니다.
threading.settrace(func)
threading 모듈에서 시작되는 모든 스레드에 대해 추적(trace) 함수를 설정합니다. run() 메서드가 호출되기 전에 이 함수는 각 스레드마다 sys.settrace()에 전달됩니다.
threading.setprofile(func)
threading 모듈에서 시작되는 모든 스레드에 대해 프로파일(profile) 함수를 설정합니다. run() 메서드가 호출되기 전에 이 함수는 각 스레드마다 sys.setprofile()에 전달됩니다.
threading.stack_size([size])
새로운 스레드를 생성할 때 사용되는 스레드 스택(stack)의 크기를 반환합니다.
threading.TIMEOUT_MAX
블로킹(blocking) 함수(Lock.acquire(), RLock.acquire(), Condition.wait() 등)의 timeout 매개변수에 허용되는 최대값을 나타내는 상수입니다.
예제 코드
import threading
def trace_function():
print("Passing the trace function")
def profile():
print("PROFILE THREAD: " + str(threading.current_thread().getName()))
class mythread(threading.Thread):
def __init__(self, thread_name, thread_ID):
threading.Thread.__init__(self)
self.thread_name = thread_name
self.thread_ID = thread_ID
def run(self):
print(str(self.thread_ID));
print("ACTIVE THREADS ARE: "+ str(threading.active_count()))
print("CURRENT THREAD IS: " + str(threading.current_thread().getName()))
my_thread1 = mythread("PP", 500)
my_thread2 = mythread("PythonProgram", 1000);
print("NAME OF THE MAIN THREAD: " + str(threading.main_thread().getName()))
print("IDENTIFICATION OF MAIN THREAD: "+ str(threading.get_ident()))
print("STACK SIZE = " + str(threading.stack_size()))
print(threading.settrace(trace_function()))
threading.setprofile(profile())
my_thread1.start()
my_thread2.start()
print("LIST OF ENUMERATION: ")
print(threading.enumerate())
print("EXIT")실행 결과
NAME OF THE MAIN THREAD: MainThread IDENTIFICATION OF MAIN THREAD: 5436 STACK SIZE = 0 Passing the trace function None PROFILE THREAD: MainThread 500 1000LIST OF ENUMERATION: ACTIVE THREADS ARE: 6 [<_MainThread(MainThread, started 5436)>, <Thread(Thread-4, started daemon 1960)>, <Heartbeat(Thread-5, started daemon 6452)>, <HistorySavingThread(IPythonHistorySavingThread, started 4304)>, <mythread(Thread-8, started 8460)>, <mythread(Thread-9, started 4668)>] EXIT CURRENT THREAD IS: Thread-8 ACTIVE THREADS ARE: 5 CURRENT THREAD IS: Thread-9