멀티스레딩과 멀티프로세싱(Multithreading and Multiprocessing in Python)
Multithreading
멀티스레딩은 하나의 프로세스 내에서 여러 스레드를 생성하여 동시에 작업을 수행하는 방식입니다. Python에서 멀티스레딩을 구현하려면 threading 모듈을 사용할 수 있습니다.
멀티스레딩 예제
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('Done')
위 코드에서는 두 개의 스레드를 생성하여 동시에 숫자와 문자를 출력합니다. thread1과 thread2는 각각 print_numbers와 print_letters 함수를 실행합니다. start() 메서드를 호출하여 스레드를 시작하고, join() 메서드를 호출하여 메인 스레드가 두 스레드의 완료를 기다리도록 합니다.
스레드 안전성
여러 스레드가 동시에 공유 자원에 접근할 때 데이터 불일치 문제가 발생할 수 있습니다. 이를 방지하기 위해 threading 모듈에서 제공하는 Lock을 사용할 수 있습니다.
import threading
counter = 0
lock = threading.Lock()
def increment_counter():
global counter
with lock:
counter += 1
threads = []
for _ in range(100):
thread = threading.Thread(target=increment_counter)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print(f'Final counter value: {counter}')
위 예제에서는 counter 변수에 100개의 스레드가 동시에 접근하여 값을 증가시키지만, lock을 사용하여 한 번에 하나의 스레드만 counter를 수정할 수 있도록 보장합니다.
Multiprocessing
멀티프로세싱은 여러 개의 프로세스를 생성하여 동시에 작업을 수행하는 방식입니다. Python에서 멀티프로세싱을 구현하려면 multiprocessing 모듈을 사용할 수 있습니다. 멀티프로세싱은 각 프로세스가 독립된 메모리 공간을 가지므로 GIL(Global Interpreter Lock) 제약을 받지 않습니다.
멀티프로세싱 예제
from multiprocessing import Process
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)
# 프로세스 생성
process1 = Process(target=print_numbers)
process2 = Process(target=print_letters)
# 프로세스 시작
process1.start()
process2.start()
# 메인 프로세스가 두 프로세스가 완료될 때까지 기다림
process1.join()
process2.join()
print('Done')
위 코드에서는 두 개의 프로세스를 생성하여 동시에 숫자와 문자를 출력합니다. process1과 process2는 각각 print_numbers와 print_letters 함수를 실행합니다. start() 메서드를 호출하여 프로세스를 시작하고, join() 메서드를 호출하여 메인 프로세스가 두 프로세스의 완료를 기다리도록 합니다.
프로세스 간 통신
멀티프로세싱에서 프로세스 간에 데이터를 주고받기 위해 Queue를 사용할 수 있습니다.
from multiprocessing import Process, Queue
def square_numbers(numbers, queue):
for n in numbers:
queue.put(n * n)
numbers = [1, 2, 3, 4, 5]
queue = Queue()
process = Process(target=square_numbers, args=(numbers, queue))
process.start()
process.join()
# 결과 출력
while not queue.empty():
print(queue.get())
위 예제에서는 square_numbers 함수가 숫자 리스트를 받아 각 숫자의 제곱을 계산한 후 Queue에 넣습니다. 메인 프로세스는 Queue에서 값을 꺼내어 출력합니다.
멀티스레딩과 멀티프로세싱을 사용하면 Python에서 동시에 여러 작업을 효율적으로 수행할 수 있습니다. 멀티스레딩은 가벼운 병렬 처리를 위해 유용하고, 멀티프로세싱은 GIL 제약을 피하기 위해 더 많은 CPU 자원을 사용할 때 유용합니다.
