본문 바로가기

Study Information Technology

Python의 threading 모듈로 병렬 작업 처리하기

728x90
반응형

Python의 threading 모듈로 병렬 작업 처리하기

Overview

Python의 threading 모듈은 병렬 작업을 관리하고 동시에 여러 작업을 실행하는 데 도움을 주는 강력한 도구입니다. 멀티스레딩을 통해 동시에 여러 작업을 수행할 수 있으며, 이는 응답성을 향상시키고, 시간 소모를 줄이며, 효율적인 자원 관리를 가능하게 합니다. 이번 설명에서는 threading 모듈의 주요 기능, 사용법, 예제, 자주 발생하는 오류 및 해결 방법에 대해 자세히 알아보겠습니다.

threading 모듈의 기본 개념

Python의 threading 모듈은 멀티스레딩을 지원하는 데 필요한 다양한 클래스와 메서드를 제공합니다. 멀티스레딩은 프로그램이 여러 작업을 동시에 수행할 수 있도록 합니다. 각 스레드는 프로그램 내에서 독립적으로 실행되며, 공유 자원에 접근할 수 있습니다.

기본 사용법

1. Thread 클래스 사용하기

threading.Thread 클래스는 새로운 스레드를 생성하는 가장 기본적인 방법입니다. 스레드를 생성하려면, Thread 클래스의 인스턴스를 만들고, target 인자에 실행할 함수 또는 메서드를 전달합니다.

예제

다음은 간단한 멀티스레딩 예제입니다. 두 개의 스레드를 생성하여 각각 다른 작업을 동시에 실행합니다.

import threading
import time

def print_numbers():
for i in range(1, 6):
print(f"Number: {i}")
time.sleep(1)

def print_letters():
for letter in 'abcde':
print(f"Letter: {letter}")
time.sleep(1)

# 스레드 생성
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)

# 스레드 시작
thread1.start()
thread2.start()

# 스레드가 완료될 때까지 대기
thread1.join()
thread2.join()

print("Both threads have finished execution.")

이 코드에서 print_numbers 함수와 print_letters 함수는 서로 다른 스레드에서 동시에 실행됩니다. start() 메서드를 호출하면 스레드가 실행을 시작하고, join() 메서드는 스레드가 끝날 때까지 기다립니다.

2. Lock 객체 사용하기

멀티스레딩을 사용할 때, 여러 스레드가 동시에 동일한 자원에 접근하면 데이터 경합이 발생할 수 있습니다. 이를 방지하기 위해 Lock 객체를 사용할 수 있습니다.

예제

다음은 Lock 객체를 사용하여 데이터 경합 문제를 해결하는 예제입니다.

import threading

# 공유 자원
shared_resource = 0
lock = threading.Lock()

def increment():
global shared_resource
with lock:
current_value = shared_resource
current_value += 1
shared_resource = current_value

threads = []
for _ in range(1000):
thread = threading.Thread(target=increment)
threads.append(thread)
thread.start()

for thread in threads:
thread.join()

print(f"Final value of shared_resource: {shared_resource}")

이 코드에서는 increment 함수가 공유 자원인 shared_resource를 수정할 때 Lock을 사용하여 동기화를 보장합니다. with lock: 문을 사용하면 스레드가 lock을 얻을 때까지 대기하게 되고, lock을 얻은 후에는 다른 스레드가 접근하지 못하도록 합니다.

자주 발생하는 오류 및 해결 방법

1. RuntimeError: thread already started

이 오류는 동일한 스레드를 두 번 시작하려고 할 때 발생합니다. 스레드는 한번만 시작할 수 있으며, 이후에는 start() 메서드를 호출할 수 없습니다.

해결 방법

스레드를 재사용하려면, 새로운 Thread 객체를 생성해야 합니다. 예를 들어:

thread1 = threading.Thread(target=my_function)
thread1.start()
thread1.join()

# 새로운 스레드를 생성하여 다시 사용
thread2 = threading.Thread(target=my_function)
thread2.start()
thread2.join()

2. AttributeError: 'Thread' object has no attribute 'join'

이 오류는 Thread 객체가 아닌 다른 객체에서 join() 메서드를 호출할 때 발생합니다. join() 메서드는 Thread 객체에만 사용할 수 있습니다.

해결 방법

join() 메서드를 호출하기 전에 Thread 객체를 올바르게 생성했는지 확인합니다.

3. GIL(Global Interpreter Lock) 문제

Python은 GIL(Global Interpreter Lock)이라는 개념을 도입하여 한 번에 하나의 스레드만 Python 바이트코드를 실행할 수 있도록 합니다. 이로 인해 CPU 집약적인 작업에서는 멀티스레딩이 성능 향상을 보장하지 않을 수 있습니다.

해결 방법

CPU 집약적인 작업에서는 멀티프로세싱을 사용하는 것이 더 효과적입니다. multiprocessing 모듈을 사용하여 각 프로세스가 독립적으로 실행되도록 할 수 있습니다.

import multiprocessing

def cpu_bound_task():
# CPU 집약적인 작업
pass

processes = []
for _ in range(multiprocessing.cpu_count()):
process = multiprocessing.Process(target=cpu_bound_task)
processes.append(process)
process.start()

for process in processes:
process.join()

참고문서

728x90
반응형