Skip to content

๐Ÿง  ืžื”ื• GIL ื‘ืคื™ื™ืชื•ืŸ, ื•ืœืžื” ื–ื” ื—ืฉื•ื‘?

๐Ÿ”’ ืžื” ื–ื” ื‘ืขืฆื GIL?

ื”ึพGIL (Global Interpreter Lock) ื”ื•ื ืžื ื’ื ื•ืŸ ืคื ื™ืžื™ ื‘ืžืคืจืฉ ืฉืœ ืคื™ื™ืชื•ืŸ (ื‘ื’ืจืกืช CPython), ืฉืžื•ื•ื“ื ืฉ ืจืง ืฉืจืฉื•ืจ ืื—ื“ ืžืจื™ืฅ ืงื•ื“ ืคื™ื™ืชื•ืŸ ื‘ื›ืœ ืจื’ืข ื ืชื•ืŸ โ€“ ื’ื ืื ื™ืฉ ืœืš ื›ืžื” ืœื™ื‘ื•ืช ืžืขื‘ื“ ืคื ื•ื™ื•ืช.

ื›ืŸ, ืืคื™ืœื• ืื ื™ืฆืจืช 10 ืฉืจืฉื•ืจื™ื โ€“ ืจืง ืื—ื“ ืžื”ื ืžืจื™ืฅ ืงื•ื“ ืคื™ื™ืชื•ืŸ ื‘ื–ืžืŸ ื ืชื•ืŸ.


๐Ÿงช ืœืžื” ื–ื” ืงื™ื™ื?

ื”ืžื ืขื•ืœ ื”ื–ื” ืงื™ื™ื ื›ื“ื™ ืœืคืฉื˜ ืืช ื ื™ื”ื•ืœ ื”ื–ื™ื›ืจื•ืŸ ื‘ืคื™ื™ืชื•ืŸ, ืฉืžืชื‘ืกืก ืขืœ ืžื ื’ื ื•ืŸ ืฉืœ ืกืคื™ืจืช ื”ืคื ื™ื•ืช (Reference Counting). ื‘ืœื™ GIL, ื”ื™ื™ื ื• ืฆืจื™ื›ื™ื ืœื˜ืคืœ ื‘ื”ืจื‘ื” ืชืงืœื•ืช ืชื—ืจื•ืช (Race Conditions) ื‘ื ื™ื”ื•ืœ ื–ื™ื›ืจื•ืŸ, ื•ื–ื” ื”ื™ื” ื”ื•ืคืš ืืช CPython ืœืžืกื•ื‘ืš ื™ื•ืชืจ ื•ื—ืฉื•ืฃ ืœื‘ืขื™ื•ืช.


๐Ÿข ืื™ืš GIL ืžืฉืคื™ืข ืขืœ ื”ื‘ื™ืฆื•ืขื™ื?

๐Ÿ’ป ืงื•ื“ ืฉืžื‘ืฆืข ื—ื™ืฉื•ื‘ื™ื:

ืื ืืชื” ืžืจื™ืฅ ืงื•ื“ ืฉื›ื•ืœื• ื—ื™ืฉื•ื‘ื™ื ืžืชืžื˜ื™ื™ื, ืœื•ืœืื•ืช, ื ื™ืชื•ื— ื ืชื•ื ื™ื โ€“ ืชืจืื” ืฉึพืฉื™ืžื•ืฉ ื‘ืฉืจืฉื•ืจื™ื ืœื ื ื•ืชืŸ ืฉื™ืคื•ืจ ืืžื™ืชื™ ื‘ื‘ื™ืฆื•ืขื™ื. ืœืคืขืžื™ื ืืคื™ืœื• ื™ื”ื™ื” ืื™ื˜ื™ ื™ื•ืชืจ.

from threading import Thread
from time import perf_counter

def cpu_task():
    print('ืžืชื—ื™ืœื™ื ื—ื™ืฉื•ื‘ ื›ื‘ื“...')
    total = 0
    for i in range(10**7):
        total += i
    print('ืกื™ื™ืžื ื• ื—ื™ืฉื•ื‘.')

start = perf_counter()
threads = [Thread(target=cpu_task) for _ in range(4)]

for t in threads:
    t.start()
for t in threads:
    t.join()

end = perf_counter()
print(f'ืกื”"ื› ื–ืžืŸ: {end - start:.2f} ืฉื ื™ื•ืช')

ื”ืชื•ืฆืื”? ื‘ืขืจืš ื›ืžื• ืื ื”ื™ื™ืช ืžืจื™ืฅ ืืช ื”ืคื•ื ืงืฆื™ื” ื‘ืจืฆืฃ 4 ืคืขืžื™ื. ืœื ื‘ืืžืช ืžืงื‘ื™ืœื™.


๐ŸŒ ืงื•ื“ ืžื‘ื•ืกืก ืงืœื˜/ืคืœื˜:

ื›ืืŸ GIL ืœื ืžืคืจื™ืข ื›ื™ ื‘ืจื’ืข ืฉืฉืจืฉื•ืจ ืžื—ื›ื” (ืœืžืฉืœ ืœืงืจื™ืื” ืžืงื•ื‘ืฅ ืื• ืจืฉืช), ื”ื•ื "ืžืฉื—ืจืจ" ืืช ื”ึพGIL ื•ืžืืคืฉืจ ืœืฉืจืฉื•ืจ ืื—ืจ ืœืจื•ืฅ. ืœื›ืŸ ื‘ืžืงืจื™ื ืฉืœ ืขื‘ื•ื“ื” ืขื API, ืžืกื“ ื ืชื•ื ื™ื, ืงื‘ืฆื™ื ื•ื›ื•' โ€“ threading ืขื•ื–ืจ.


๐Ÿš€ ืคืชืจื•ื ื•ืช โ€“ ืื™ืš ื›ืŸ ืžืจื™ืฆื™ื ืงื•ื“ ืžืงื‘ื™ืœื™ "ืืžื™ืชื™"?

๐Ÿงฉ 1. ืฉื™ืžื•ืฉ ื‘ึพmultiprocessing

ื”ืžื•ื“ื•ืœ multiprocessing ื™ื•ืฆืจ ืชื”ืœื™ื›ื™ื ื ืคืจื“ื™ื, ื•ืœื ืฉืจืฉื•ืจื™ื โ€“ ื•ืœื›ืŸ ื›ืœ ืชื”ืœื™ืš ืžืงื‘ืœ GIL ืžืฉืœื•.

from multiprocessing import Process

def cpu_task():
    total = 0
    for i in range(10**7):
        total += i

processes = [Process(target=cpu_task) for _ in range(4)]

for p in processes:
    p.start()
for p in processes:
    p.join()

โœ… ืชื•ืฆืื•ืช: ื”ืจื‘ื” ื™ื•ืชืจ ืžื”ื™ืจ ื›ืฉืžื“ื•ื‘ืจ ืขืœ ื—ื™ืฉื•ื‘ื™ื ื›ื‘ื“ื™ื. ื›ืœ ืชื”ืœื™ืš ืจืฅ ืขืœ ืœื™ื‘ื” ืžืฉืœื•.


โš™๏ธ 2. ืฉื™ืžื•ืฉ ื‘ึพasyncio

ื›ืฉื™ืฉ ื”ืจื‘ื” ืคืขื•ืœื•ืช ืงืœื˜/ืคืœื˜ โ€“ ืืคืฉืจ ื’ื ืœื”ืฉืชืžืฉ ื‘ึพasyncio, ืฉื”ื•ื ืคืชืจื•ืŸ ืžื‘ื•ืกืก ืœื•ืœืืช ืื™ืจื•ืขื™ื. ื–ื” ืœื "ืžืงื‘ื™ืœื™ ืืžื™ืชื™" ืื‘ืœ ืžืื•ื“ ื™ืขื™ืœ ื•ื—ืกื›ื•ื ื™ ื‘ืžืฉืื‘ื™ื.

import asyncio

async def fetch_data():
    print("ืžืชื—ื™ืœื™ื ืงืจื™ืื” ืœืฉืจืช...")
    await asyncio.sleep(1)
    print("ืงื™ื‘ืœื ื• ืชื’ื•ื‘ื”.")

async def main():
    await asyncio.gather(*(fetch_data() for _ in range(5)))

asyncio.run(main())

๐Ÿงญ ืœืกื™ื›ื•ื

ืกื•ื’ ืžืฉื™ืžื”ืคืชืจื•ืŸ ืžื•ืขื“ืฃ
ื—ื™ืฉื•ื‘ื™ื ื›ื‘ื“ื™ืmultiprocessing
ืงืœื˜/ืคืœื˜ (I/O)threading / asyncio
ืขื‘ื•ื“ื” ืขื APIsasyncio ืื• threading
ืจื™ื‘ื•ื™ ืงื‘ืฆื™ืthreading


ื›ืชื™ื‘ืช ืชื’ื•ื‘ื”

ื”ืื™ืžื™ื™ืœ ืœื ื™ื•ืฆื’ ื‘ืืชืจ. ืฉื“ื•ืช ื”ื—ื•ื‘ื” ืžืกื•ืžื ื™ื *