computer engineering

Python - GIL와 메모리 관리

제이훈 : 세상 모든 지식의 탐구자 2025. 5. 7. 21:13

파이썬 GIL와 메모리 관리

1. GIL (Global Interpreter Lock)이란?

CPython 인터프리터는 한 번에 하나의 쓰레드만 바이트코드를 실행할 수 있도록 제한하는 전역 락(GIL)을 사용합니다.
모든 쓰레드는 GIL을 획득해야만 실행 가능
❌ 문제: 여러 쓰레드가 동시에 참조 카운트를 조작하면 메모리 오류 발생 가능
✔ 해결: GIL을 통해 바이트코드 실행을 직렬화하여 안전 보장

2. 멀티쓰레딩은 못 쓰나?

CPU 바운드 작업에서는 GIL로 인해 성능 향상 거의 없음.
I/O 바운드 작업(네트워크, 파일, DB 등)은 GIL이 자동 해제되어 효과 있음
✔ 대안: 멀티프로세싱, C 확장, async/await 활용

3. GIL의 동작 방식

- 쓰레드는 GIL을 획득해야 Python 바이트코드를 실행 가능
- 인터프리터는 100개의 바이트코드마다 GIL을 다른 쓰레드에 양보
- Numpy 등 C 확장 모듈은 GIL 없이 병렬 연산 수행 가능

4. Reference Counting (참조 카운팅)

Python의 기본 메모리 관리 기법.
참조 수가 0이면 즉시 해제
❌ 문제: 순환 참조 발생 시 참조 수가 0이 되지 않아 메모리 누수 가능
✔ 해결: Garbage Collection을 통한 보완 필요

5. Garbage Collection (가비지 컬렉션)

순환 참조 제거를 위한 보완 메커니즘.
gc 모듈이 Mark and Sweep 알고리즘을 사용
✔ 구조: 객체를 0, 1, 2 세대로 구분하여 세대별로 수집 주기 조절
✔ 원리: 참조 그래프를 분석해 루트에서 도달 불가능한 객체 제거

6. 순환 참조 예시


class Node:
    def __init__(self):
        self.ref = None

a = Node()
b = Node()

a.ref = b
b.ref = a

del a
del b
# 참조 카운트는 0이 아님 → 가비지 컬렉터가 처리해야 함
import gc
gc.collect()

🧠 요약

  • GIL: CPython에서 메모리 안전을 위해 바이트코드 실행을 직렬화
  • Reference Counting: 객체 참조 수를 기준으로 자동 메모리 해제
  • Garbage Collection: 순환 참조를 탐지해 메모리 누수 방지
  • 멀티쓰레딩: I/O에는 유용, CPU 병렬성은 멀티프로세싱이 대안