deflets_go(i, c): print(f'[Thread {i}] Started (id : {threading.get_ident()})') for j in range(5): c.count = c.count + 1 print(f'[Thread {i}] {c.count}')
if __name__ == "__main__": tc = TestClass() for i in range(5): th = threading.Thread(target=lets_go, args=[i, tc]) th.start()
결과. 여러 쓰레드가 서로 경쟁하면서 Shared Data에 접근하는 모습을 볼 수 있다. 순서 X
deflets_go(i, c): print(f'[Thread {i}] Started (id : {threading.get_ident()})') # Double Lock _lock.acquire() _lock.acquire() for j in range(5): c.count = c.count + 1 print(f'[Thread {i}] {c.count}') # Single Release _lock.release()
if __name__ == "__main__": tc = TestClass() for i in range(5): th = threading.Thread(target=lets_go, args=[i, tc]) th.start()
결과. 최초 쓰레드에서 Lock을 재획득하는 순간 쓰레드가 Block되어 나머지 쓰레드도 Shared Data에 접근이 안 됨.
1 2 3 4 5
[Thread 0] Started (id : 123145407381504) [Thread 1] Started (id : 123145412636672) [Thread 2] Started (id : 123145417891840) [Thread 3] Started (id : 123145423147008) [Thread 4] Started (id : 123145428402176)
4. Lock 재획득 (with RLock)
RLock을 사용하면 Lock을 재획득하더라도 일단 Return되기 때문에 한 쓰레드의 구문이 진행은 되도록 함.
deflets_go(i, c): print(f'[Thread {i}] Started (id : {threading.get_ident()})') # Double Lock _lock.acquire() _lock.acquire() for j in range(5): c.count = c.count + 1 print(f'[Thread {i}] {c.count}') # Single Release _lock.release()
if __name__ == "__main__": tc = TestClass() for i in range(5): th = threading.Thread(target=lets_go, args=[i, tc]) th.start()
쓰레드 0이 Lock을 두 번 걸었기 때문에 나머지 쓰레드들은 Shared Data에 접근할 수 없다. 하지만 쓰레드 0이 완료된 후 띄워진 쓰레드 2, 그리고 쓰레드 2가 완료된 후 띄워진 쓰레드 4는 같은 쓰레드이기 때문에 (id 참고) Lock을 풀지 않아도 구문이 실행된다.