하나의 프로세스에서 도는 작업 들이며, 각각의 thread는 자신의 고유 stack 공간과, register 공간을 가짐.
여러 쓰레드가 하나의 프로세스에서 돌 수 있으며, 각각의 쓰레드는 동일한 데이터를 공유할 수 있음.
thread is light weight process
from threading import Thread
def func_simple(length):
sum_f1 = 0
for x in range(0, length):
sum_f1 += x
print(f"sum is {sum_f1}")
def func_square(length):
sum_f2 = 0
for x in range(0, length):
sum_f2 += x * x
print(f"square sum is {sum_f2}")
def func_cubes(length):
sum_f3 = 0
for x in range(0, length):
sum_f3 += x * x * x
print(f"cube sum is {sum_f3}")
def do_threading():
length = 3
thread_simple = Thread(target=func_simple, args=(length, ))
thread_square = Thread(target=func_square, args=(length, ))
thread_cubes = Thread(target=func_cubes, args=(length, ))
thread_simple.start()
thread_square.start()
thread_cude.start()
thread_simple.join()
thread_square.join()
thread_cude.join()
do_threading()
# "sum is 3" 0 + 1 + 2
# "square sum is 5" 0 + 1 + 4
# "cube sum 9 " 0 + 1 + 8
여러개의 thread들이 동일한 데이터에 동시에 접근할 수 있고, 다른 thread가 데이터를 변경시키는 과정에 그 뒤에 오는 thread가 데이터를 사용하려면 문제가 발생 —> lock을 통해 해결
from threading import Thread, Lock
thread_lock = Lock()
my_global_string = "Hello World"
def add_prefix(prefix_to_add):
global my_global_string
with thread_lock:
my_global_string = prefix_to_add + " " + my_global_string
def add_suffix(suffix_to_add):
global my_global_string
with thread_lock:
my_global_string = my_global_string + " " + suffix_to_add
def do_threading():
thread_prefix = Thread(target=add_prefix, args=('YOLO', ))
thread_suffix = Thread(target=add_suffix, args=('BYE'))
thread_prefix.start()
thread_suffix.start()
thread_prefix.join()
thread_suffix.join()
global my_global_string
print(f"final_string is {my_global_string}")
do_threading()
# 'YOLO Hello World BYE'
하나의 공유 변수에 대한 acquire를 여러번 할 수 있음. [deadlock 을 막기 위해]
from threading import RLock
lock = RLock()
def factorial(n):
assert n > 0
if n == 1:
return 1
with lock:
out = n * factorial(n - 1)
return out
# Lock 이라면 deadlock 걸림.