About me
home
Portfolio
home

Synchronous 실습

날짜
2023/07/19
태그
파이썬

Lock을 사용한 스레드 간 동기화

# 스레드 동기화(Thread Synchronization)를 위한 Lock 사용 성공 예제 import logging from concurrent.futures import ThreadPoolExecutor import time import threading class DataStore: # 공유 변수(value) def __init__(self): self.value = 0 # Lock 선언 self._lock = threading.Lock() # 변수 업데이트 함수 def update(self, n): logging.info("Thread %s: starting update", n) # 뮤텍스 & Lock 동기화(Thread synchronization) 사용 # Lock 획득 self._lock.acquire() logging.info("Thread %s has lock", n) local_copy = self.value local_copy += 1 time.sleep(0.1) self.value = local_copy logging.info("Thread %s about to release lock", n) # Lock 반환 self._lock.release() logging.info("Thread %s: finishing update", n) if __name__ == "__main__": # Logging format 설정 format = "%(asctime)s: %(message)s" logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S") # 클래스 인스턴스화 store = DataStore() logging.info("Testing update. Starting value is %d.", store.value) # With Context 시작 with ThreadPoolExecutor(max_workers=2) as executor: for n in ['First', 'Second', 'Third']: executor.submit(store.update, n) logging.info("Testing update. Ending value is %d.", store.value)
Python
복사
스레드 Sync(실패).py
1.1KB
스레드 Sync(성공).py
1.5KB
클래스 DataStore는 공유 변수 self.value와 lock 객체 self._lock을 소유한다. update 메소드는 스레드가 해당 객체의 value를 안전하게 변경하는 방법을 보여준다. 이 메소드는 self._lock.acquire()를 사용하여 lock을 획득하고, 작업이 끝나면 self._lock.release()를 사용하여 lock을 반환한다. 이런 방식으로, 한 번에 하나의 스레드만 value를 수정할 수 있도록 동기화한다.
메인 함수에서는 ThreadPoolExecutor를 사용하여 세 개의 스레드를 생성하고, 각 스레드에서 DataStore 객체의 update 메소드를 호출한다. 이때, 인자로 'First', 'Second', 'Third'를 전달한다.
스레드가 update 메소드를 호출할 때마다, 해당 스레드는 lock을 획득하여 value를 안전하게 1 증가시키고, lock을 반환한다. 이로 인해 각 스레드의 연산이 겹치지 않고 순차적으로 실행되어, value 값이 올바르게 증가한다.
마지막으로, 모든 스레드의 작업이 완료된 후 value의 최종 값을 출력하여, 각 스레드가 value를 제대로 갱신했음을 확인한다. 이 코드를 실행하면, 세 개의 스레드가 각각 한 번씩 value를 증가시키므로, 최종 value3이 될 것이다. Lock을 사용하지 않은 실패 예제 코드는 최종 value2가 나온다.

Next → Asynchronous 이론