파이썬의 스레드 작업 시, 메모리에서 객체는 복사 없이 모든 스레드에 즉시 접근 가능합니다. 하지만 multiprocessing을 통한 프로세스 작업 시, 표준 파이썬 객체(예: 목록, 사전)는 직렬화를 통해 프로세스 간에 전달되며(보통 pickle을 통해), 각 프로세스는 객체의 사본을 받습니다. 한 프로세스에서 객체를 변경하면 다른 프로세스의 사본에는 반영되지 않습니다.
multiprocessing.Manager().dict()와 같은 특별한 구조를 사용해야 합니다.# 다중 프로세스 from multiprocessing import Process, Manager def worker(d): d['a'] = 42 if __name__ == '__main__': # 일반 dict는 프로세스 간에 작동하지 않음 managed_dict = Manager().dict() p = Process(target=worker, args=(managed_dict,)) p.start(); p.join() print(managed_dict['a']) # 42
어떤 경우에 한 프로세스에서 일반 목록(list)을 수정하면 다른 프로세스에 반영될까요?
절대 없습니다. multiprocessing을 사용할 경우, 일반 파이썬 객체는 프로세스 간에 공유되지 않습니다. 공유를 위해서는 Manager 객체(예: Manager().list(), Manager().dict.)와 같은 특별한 원시 객체를 사용해야 하며, 이는 프로세스 간 상태를 동기화합니다.
이야기
웹 크롤러 개발 팀은 작업 큐를 목록으로 초기화하고 이를 multiprocessing을 통해 프로세스 사이에서 나누었습니다. 작업이 "사라지는" 경우가 있었던 이유는 프로세스가 서로의 업데이트를 보지 못했기 때문입니다. Manager().list()를 사용하는 것으로 수정했습니다.
이야기
분석 서비스에서는 로그를 쓰레드 내의 중첩된 dict에 수집하려고 하였습니다. 높은 부하 상황에서는 이로 인해 경쟁 상태가 발생하고 데이터가 손상되었습니다.
이야기
ETL 서비스에서 데이터 처리 단계에서 수집된 객체를 여러 프로세스에 모으려 하여 데이터 중복/손실이 발생했습니다: 프로그래머는 각 프로세스가 공통 구조의 사본과 작업하고 있다는 것을 고려하지 않았습니다.