π Thread(μ€λ λ)λ?
μ€λ λ(thread)λ νλ‘μΈμ€(process) λ΄μμ μ€μ λ‘ μμ μ μννλ 주체λ₯Ό μλ―Ένλ€.
ν νλ‘μΈμ€ λ΄μμ μ¬λ¬ κ°μ μμ λ€μ΄ λμμ μ€νλ μ μμ΄μΌ νλλ° μ΄κ²μ΄ μ€λ λμ΄λ€.
μ€λ λλ νλ‘μΈμ€κ° κ°μ§κ³ μλ λ©λͺ¨λ¦¬λ₯Ό 곡μ νλ€.
λν, λ κ° μ΄μμ μ€λ λλ₯Ό κ°μ§λ νλ‘μΈμ€λ₯Ό λ©ν°μ€λ λ νλ‘μΈμ€(multi-threaded process)λΌκ³ νλ€.
νμ΄μ¬ νλ‘κ·Έλ¨μ κΈ°λ³Έμ μΌλ‘ νλμ μ°λ λ(single thread)μμ μ€νλλ€.(νμ΄μ¬μ GIL μ μ± ) λ°λΌμ μ½λλ₯Ό λ³λ ¬λ‘ μ€ννκΈ° μν΄μλ λ³λμ μ°λ λλ₯Ό μμ±ν΄μΌ νλλ°, νμ΄μ¬ μ°λ λλ₯Ό μμ±νκΈ° μν΄μλ threadingλͺ¨λμ μ¬μ©ν μ μλ€.
κ·Έλ λ€λ©΄ νλ‘μΈμ€μ μ€λ λμ μ°¨μ΄λ 무μμΈκ°?
νλ‘μΈμ€λ νλ‘κ·Έλ¨μ΄ μ€νλμ λμκ°κ³ μλ μνλΌκ³ μκ°νλ©΄ λλ€. μ¦, μ¬μ©μκ° μμ±ν νλ‘κ·Έλ¨μ΄ μ΄μ체μ μ μν΄ λ©λͺ¨λ¦¬ 곡κ°μ ν λΉλ°μ μ€νμ€μΈ κ²μ λ§νλ€. μ΄λ¬ν νλ‘μΈμ€λ νλ‘κ·Έλ¨μ μ¬μ©λλ λ°μ΄ν°μ λ©λͺ¨λ¦¬ λ±μ μμ κ·Έλ¦¬κ³ μ€λ λλ‘ κ΅¬μ±λλ€.
νλ‘μΈμ€μ μ€λ λλ μ²λ¦¬ λ°©μ μ μ°¨μ΄κ° μλ κ±°λΌκ³ μκ°νλ©΄ λλ€.
β νλ‘μΈμ€
- ν νλ‘μΈμ€λ λ§€λ² νλμ λ‘κ·ΈμΈλ§ μ²λ¦¬ν μ μκΈ° λλ¬Έμ λμμ μ²λ¦¬ν μκ° μλ€.
- νλ‘μΈμ€λ κ°μκ° κ³ μ ν λ©λͺ¨λ¦¬ μμμ κ°μ§κΈ° λλ¬Έμ μ€λ λμ λΉνλ©΄ λ©λͺ¨λ¦¬ μ¬μ©μ΄ λμ΄λλ€λ λ¨μ μ΄ μμ§λ§, μ΄ λ°©μμ ν΅ν΄ μ±κΈ λ¨Έμ μν€ν μ²λ‘λΆν° μ¬λ¬ λ¨Έμ μ μ¬μ©νλ λΆμ° μ΄ν리μΌμ΄μ μΌλ‘ μ½κ² μ ν κ°λ₯
- νλ‘μΈμ€μ μμλ ꡬκΈν¬λ‘¬μ νμ μκ°νλ©΄ λλ€.
- ν νμ λ¬Έμ κ° μ겨λ λ€λ₯Έ νμ μν₯μ΄ μλ€.
β μ€λ λ
- ν νλ‘μΈμ€ λ΄μμ μ¬λ¬κ°μ μ€λ λλ‘ μμ μ μ²λ¦¬νλ κ²(λ©ν°μ€λ λ)
ex) pycharmμμ μΆμ²μ½λλ 보μ¬μ£Όκ³ μ€ννλ λμμ λλ²κΉ νλ©΄μ μμ νλ κ²
- μ€λ λμ μμλ‘λ μλμ° νμ μκ°ν΄λ³΄λ©΄ λλ€.
- ν νμ λ¬Έμ κ° μκΈ°λ©΄ λͺ¨λ νμ μν₯μ λ―Έμ³ μ μ²΄κ° κΊΌμ§κ² λλ€.
π Lockμ΄λ
Lock μ python threading ν¨ν€μ§μμ μ§μνλ€.
lockμ acquire() νλ©΄ ν΄λΉ μ€λ λλ§ κ³΅μ λ°μ΄ν°μ μ κ·Όν μ μκ³ , lockμ release() ν΄μΌλ§ λ€λ₯Έ μ€λ λμμ 곡μ λ°μ΄ν°μ μ κ·Όν μ μλ€.
Lockμ μ¬μ©νλ μ΄μ λ νλμ μ°λ λλ§ μ§μ νκ² νλλ‘ νκΈ° μν΄μμ΄λ€. λ΄κ° Lockμ μ¬μ©νλ μ΄μ λ λ€μκ³Ό κ°λ€. I/O μμ μ μ€νν λ νμ΄μ¬μ GIL(Global Interpreter Lock) μ μ± κ³Ό λ€λ₯΄κ² μ¬λ¬ κ°μ μ€λ λλ₯Ό μ¬μ©ν΄μ λμμ²λ¦¬λ₯Ό μ§ννλλ° κ·Έλ thread1μ΄ μ λ°μ΄νΈ ν΄λμ global λ³μμ λν΄μ 24μκ° λμμ μ μ§λκ² ν΄λκ³ μΆμκΈ° λλ¬Έμ΄λ€. μ¦, λμμ thread1κ³Ό thread2κ° κ³΅μ λ³μμ μ κ·Όν΄μ μ€λ³΅μΌλ‘ μ λ°μ΄νΈκ° λμ§ μκ² νκΈ° μν΄μ μ¬μ©νλ€.
νμ΄μ¬μ GIL μ μ± λλ¬Έμ νμ΄μ¬μ μ±κΈμ€λ λ μΈμ΄λ‘ λΆλ¦¬μ§λ§ κ°μ λ‘ threadλ₯Ό μμ±ν΄μ Lock ν μ€νΈλ₯Ό μ§νν΄λ³΄μλ€.
1. thread 2κ° μμ±, Lock λ―Έμ μ©
import threading
import time
shared_number = 0
def thread_1(number):
global shared_number
print("thread_1 number = ", end=""), print(number)
for i in range(number):
shared_number += 1
def thread_2(number):
global shared_number
print("thread_2 number = ", end=""), print(number)
for i in range(number):
shared_number += 1
if __name__ == "__main__":
threads = []
start_time = time.time()
t1 = threading.Thread(target=thread_1, args=(10000000,)) #μ²λ§
t1.start()
threads.append(t1)
t2 = threading.Thread(target=thread_2, args=(10000000,)) #μ²λ§
t2.start()
threads.append(t2)
for t in threads:
t.join() # μ°λ λκ° λͺ¨λ μμ
μ λ§μΉ λκΉμ§ κΈ°λ€λ¦¬λ κ²
print("--- %s seconds ---" % (time.time() - start_time))
print("shared_number=", end=""), print(shared_number)
print("end of main")
----------------------------------------------------------------------
thread_1 number = 10000000
thread_2 number = 10000000
--- 0.8049440383911133 seconds ---
shared_number=12506270
end of main
threadλ₯Ό 2κ° μμ±νκ³ shared_numberμ λν΄ Lockμ μ μ©νμ§ μμ μνμμ κ²°κ³Όκ°μ μμνλ 20,000,000 κ³Όλ λ€λ₯΄κ² λμ¨λ€.
κ·Έ μ΄μ λ κ°μ λ³μλ₯Ό λμμ μ κ·ΌνκΈ° λλ¬Έμ΄λ€.
2. thread2κ° μμ±, Lock μ μ©
import threading
import time
shared_number = 0
lock = threading.Lock() # threadingμμ Lock ν¨μ κ°μ Έμ€κΈ°
def thread_1(number):
global shared_number
print("thread_1 number = ", end=""), print(number)
lock.acquire() # μμ
μ΄ λλκΈ° μ κΉμ§ λ€λ₯Έ μ°λ λκ° κ³΅μ λ°μ΄ν° μ κ·Όμ κΈμ§
for i in range(number):
shared_number += 1
lock.release() # lock ν΄μ
def thread_2(number):
global shared_number
print("thread_2 number = ", end=""), print(number)
lock.acquire() # thread_2 μ κΈ
for i in range(number):
shared_number += 1
lock.release() # thread_2 ν΄μ
if __name__ == "__main__":
threads = []
start_time = time.time()
t1 = threading.Thread(target=thread_1, args=(10000000,)) #μ²λ§
t1.start() # start() ν¨μλ‘ μ°λ λλ₯Ό μμ
threads.append(t1)
t2 = threading.Thread(target=thread_2, args=(10000000,)) #μ²λ§
t2.start()
threads.append(t2)
for t in threads:
t.join() # μ°λ λκ° λͺ¨λ μμ
μ λ§μΉ λκΉμ§ κΈ°λ€λ¦¬λ κ²
print("--- %s seconds ---" % (time.time() - start_time))
print("shared_number=", end=""), print(shared_number)
print("end of main")
---------------------------------------------------------------
thread_1 number = 10000000
thread_2 number = 10000000
--- 0.7583627700805664 seconds ---
shared_number=20000000
end of main
shared_numberλ₯Ό Lockμ ν΅ν΄ μ°λ λλ₯Ό λκΈ°νμμΌμ£Όμκ³ κ·Έ κ²°κ³Ό μ νν κ°(20,000,000)μ μ»κ²λμλ€.
π μ°Έκ³
https://velog.io/@kho5420/Python-Thread-and-Lock-%EC%93%B0%EB%A0%88%EB%93%9C%EC%99%80-%EB%9D%BD
https://nowonbun.tistory.com/667
'Language > Python' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[Python] functools μ partial | LIM (0) | 2022.07.09 |
---|---|
[Python] Flaskμ FastAPIλ‘ Python λμμ± ν μ€νΈ | LIM (0) | 2022.07.03 |
[Python] μμΈμ²λ¦¬ try, except, finally and raise | LIM (0) | 2022.06.24 |
[Python] μΆμ λ©μλ ABCμ μ μμ μ¬μ© | LIM (0) | 2022.06.19 |
[Python] *args μ **kwargs | LIM (0) | 2021.01.27 |
λκΈ