프로그래밍파이썬 개발자

파이썬에서 스레드나 프로세스 간에 복합 객체(예: 사전 목록)를 전달할 때 어떤 일이 발생하나요? 변동성이 있는 컬렉션과 관련된 다중 스레드 및 다중 프로세스 애플리케이션을 프로그래밍할 때 기억해야 할 중요한 점은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

파이썬의 스레드 작업 시, 메모리에서 객체는 복사 없이 모든 스레드에 즉시 접근 가능합니다. 하지만 multiprocessing을 통한 프로세스 작업 시, 표준 파이썬 객체(예: 목록, 사전)는 직렬화를 통해 프로세스 간에 전달되며(보통 pickle을 통해), 각 프로세스는 객체의 사본을 받습니다. 한 프로세스에서 객체를 변경하면 다른 프로세스의 사본에는 반영되지 않습니다.

주요 차이점:

  • 다중 스레딩 (threading): 모든 스레드는 공통의 주소 공간에서 작동합니다. 모든 객체(포함된 컬렉션 포함)는 공유됩니다.
  • 다중 프로세스 (multiprocessing): 각 프로세스는 자신의 메모리를 가지고 있으며, 객체는 직렬화를 통해 전달됩니다. 프로세스 간 교환을 위해서는 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
  • 일반 dict를 사용했더라면, 프로세스에서의 변화는 주 프로세스에 보이지 않았을 것입니다.

장난꾸러기 질문.

어떤 경우에 한 프로세스에서 일반 목록(list)을 수정하면 다른 프로세스에 반영될까요?

답변:

절대 없습니다. multiprocessing을 사용할 경우, 일반 파이썬 객체는 프로세스 간에 공유되지 않습니다. 공유를 위해서는 Manager 객체(예: Manager().list(), Manager().dict.)와 같은 특별한 원시 객체를 사용해야 하며, 이는 프로세스 간 상태를 동기화합니다.

주제의 미세한 차이에 대한 실제 오류의 예.


이야기

웹 크롤러 개발 팀은 작업 큐를 목록으로 초기화하고 이를 multiprocessing을 통해 프로세스 사이에서 나누었습니다. 작업이 "사라지는" 경우가 있었던 이유는 프로세스가 서로의 업데이트를 보지 못했기 때문입니다. Manager().list()를 사용하는 것으로 수정했습니다.


이야기

분석 서비스에서는 로그를 쓰레드 내의 중첩된 dict에 수집하려고 하였습니다. 높은 부하 상황에서는 이로 인해 경쟁 상태가 발생하고 데이터가 손상되었습니다.


이야기

ETL 서비스에서 데이터 처리 단계에서 수집된 객체를 여러 프로세스에 모으려 하여 데이터 중복/손실이 발생했습니다: 프로그래머는 각 프로세스가 공통 구조의 사본과 작업하고 있다는 것을 고려하지 않았습니다.