티스토리 뷰

[lock: 락]


다수의 스레드 실행으로 공유자원에 접급할 때 필요한 메커니즘이다.


이를 이해하려면 1개의 화장실과 여러 명의 사람을 생각하면 된다.


한명이 화장실에서 샤워를 하면 다른 사람이 볼 수 없게 문을 잠가야 한다.


파이썬 락은 문을 잠그는 동기화 프리미티브다.


이는 락, 언락 상태가 있고 언락 에서만 락을 요청할 수 있다.



import threading
import time


count = 1


def worker_a():
global count
while count < 10:
count += 1
print(f"worker A is incrementing counter to {count}")
time.sleep(1)


def worker_b():
global count
while count > -10:
count -= 1
print(f"worker B is decrementing counter to {count}")
time.sleep(1)


def main():
t0 = time.time()
thread1 = threading.Thread(target=worker_a)
thread2 = threading.Thread(target=worker_b)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
t1 = time.time()
print(f"excution time {t1-t0}")


if __name__ == '__main__':
main()


이 코드는 락없이 아무렇게나 count 변수에 접근할 수 있다.


이렇게 하면 두 스레드에서 서로 감소, 증가가 동시에 되기 때문에


스레드가 종료가 되지 않고 두개의 스레드는 무한정 돌아가게 된다.


락을 추가해서 안전한 상태로 접근하게 해야 한다.



import threading
import time


count = 1
lock = threading.Lock()


def worker_a():
global count
lock.acquire()
try:
while count < 10:
count += 1
print(f"worker A is incrementing counter to {count}")
time.sleep(1)
finally:
lock.release()


def worker_b():
global count
lock.acquire()
try:
while count > -10:
count -= 1
print(f"worker B is decrementing counter to {count}")
time.sleep(1)
finally:
lock.release()


def main():
t0 = time.time()
thread1 = threading.Thread(target=worker_a)
thread2 = threading.Thread(target=worker_b)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
t1 = time.time()
print(f"excution time {t1-t0}")


if __name__ == '__main__':
main()


이렇게 서로 락을 제한해서 하면


먼저 리소스에 접근한 스레드가 while 조건을 마칠때 까지 다른 스레드는


count 에 접근하지 못한다.


따라서 한개의 스레드가 종료하고 그 다음에 다른 스레드가 동작하고 종료하게 된다.

댓글