https://docs.python.org/3/tutorial/stdlib2.html#multi-threading
사용 예시
- threading.Thread를 상속한 AsyncZip 클래스가 압축을 담당합니다.
- 메인 스레드는 사용자 인터페이스를 계속 돌리고, 압축 스레드는 뒤에서 파일을 처리합니다.
import threading, zipfile
class AsyncZip(threading.Thread):
def __init__(self, infile, outfile):
super().__init__()
self.infile = infile
self.outfile = outfile
def run(self):
with zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED) as zf:
zf.write(self.infile)
print('압축 완료:', self.infile)
background = AsyncZip('data.txt', 'data.zip')
background.start()
print('메인 프로그램은 계속 실행 중입니다.')
background.join() # 백그라운드 작업이 끝날 때까지 기다림
print('백그라운드 작업이 끝났습니다.')- 단일 관리자 스레드:
- 공유 자원을 딱 한 스레드만 직접 다루게 하고, 나머지는 queue.Queue에 요청을 넣도록 설계하면 경합 자체를 없앨 수 있습니다.
- 예컨대 DB 쓰기를 담당하는 전용 스레드가 큐에서 요청을 받아 처리하면 다른 스레드는 단순히 큐에 작업을 넣기만 하면 됩니다.
- 작업 분리:
- 한 스레드가 읽기/쓰기/업데이트를 동시에 하지 않게 책임을 분리합니다.
- 읽기만 하는 스레드와 쓰기 담당 스레드를 나누거나,
- 상태 변경은 특정 스레드에서만 하도록 규칙을 둡니다.
- 동기화 최소화:
- 꼭 공유해야 하는 데이터만 공유하고,
- 나머지는 스레드별로 지역 상태를 유지합니다.
- 필요 시 threading.Lock, RLock, Semaphore 등을 사용하되,
- 잠금 범위를 최소한으로 줄여 데드락을 피합니다.
- 불변 데이터 사용:
- 가능하면 불변 객체(튜플, 문자열 등)를 공유하고,
- 변경 가능한 구조는 복사본을 전달합니다.
- 복사 비용이 적은 설정값,
- 메시지 등은 이런 방식이 간단하고 안전합니다.
- 테스트 및 로깅:
- 스레드 간 타이밍 문제는 재현이 어려우므로, 큐 상태, 락 획득/반납 시점 등을 로그로 남기고,
- 가능한 한 작은 단위로 테스트해 두면 문제 발생 시 추적이 쉬워집니다.
← python 3.14으로