공유자원을 Lock & unLock 하는 2가지 방식에 대한 정리.
<1번째 방법>
import logging
from concurrent.futures import ThreadPoolExecutor
import time
import threading
class FakeDataStore:
# 공유 변수(value)
def __init__(self): # 스택영역
self.value = 0
self._lock = threading.Lock()
# 변수 업데이트 함수
def update(self, n):
logging.info('Thread ***{}: starting update'.format(n))
# 뮤텍스 & Lock 등 동기화(Thraed synchronization 필요)
# Lock 획득 / 방법1
self._lock.acquire()
logging.info('Thread ***{} has locked / local_copy({})'.format(n, self.value))
local_copy = self.value
local_copy += 1
time.sleep(0.1)
self.value = local_copy
logging.info('Thread ***{} has unlocked / local_copy({})'.format(n, self.value))
# Lock 반환
self._lock.release()
logging.info('Thread ***{}: ending update'.format(n))
def main():
# Logging format 설정
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")
logging.info('Main-Thread : before creating and running thread')
# 클래스 인스턴스화
store = FakeDataStore()
logging.info('Testing *** . Starting value is ({})'.format(store.value))
# With Context
with ThreadPoolExecutor(max_workers=2) as executor:
for n in['First', 'Second', 'Third']: # 인자가 1개일 경우
executor.submit(store.update, n)
logging.info('Testing *** . Ending value is ({})'.format(store.value))
if __name__=='__main__':
main()
--------------------------------------------------[result]
14:33:32: Main-Thread : before creating and running thread
14:33:32: Testing *** . Starting value is (0)
14:33:32: Thread ***First: starting update
14:33:32: Thread ***First has locked / local_copy(0)
14:33:32: Thread ***Second: starting update
14:33:33: Thread ***First has unlocked / local_copy(1)
14:33:33: Thread ***First: ending update
14:33:33: Thread ***Third: starting update
14:33:33: Thread ***Second has locked / local_copy(1)
14:33:33: Thread ***Second has unlocked / local_copy(2)
14:33:33: Thread ***Second: ending update
14:33:33: Thread ***Third has locked / local_copy(2)
14:33:33: Thread ***Third has unlocked / local_copy(3)
14:33:33: Thread ***Third: ending update
14:33:33: Testing *** . Ending value is (3)
<2번째 방법>
import logging
from concurrent.futures import ThreadPoolExecutor
import time
import threading
class FakeDataStore:
# 공유 변수(value)
def __init__(self): # 스택영역
self.value = 0
self._lock = threading.Lock()
# 변수 업데이트 함수
def update(self, n):
logging.info('Thread ***{}: starting update'.format(n))
# 뮤텍스 & Lock 등 동기화(Thraed synchronization 필요)
# Lock 획득 / 방법2
with self._lock:
logging.info('Thread ***{} has locked / local_copy({})'.format(n, self.value))
local_copy = self.value
local_copy += 1
time.sleep(0.1)
self.value = local_copy
logging.info('Thread ***{} has unlocked / local_copy({})'.format(n, self.value))
logging.info('Thread ***{}: ending update'.format(n))
def main():
# Logging format 설정
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")
logging.info('Main-Thread : before creating and running thread')
# 클래스 인스턴스화
store = FakeDataStore()
logging.info('Testing *** . Starting value is ({})'.format(store.value))
# With Context
with ThreadPoolExecutor(max_workers=2) as executor:
for n in['First', 'Second', 'Third']: # 인자가 1개일 경우
executor.submit(store.update, n)
logging.info('Testing *** . Ending value is ({})'.format(store.value))
if __name__=='__main__':
main()
--------------------------------------------------[result]
14:35:44: Main-Thread : before creating and running thread
14:35:44: Testing *** . Starting value is (0)
14:35:44: Thread ***First: starting update
14:35:44: Thread ***First has locked / local_copy(0)
14:35:44: Thread ***Second: starting update
14:35:45: Thread ***First has unlocked / local_copy(1)
14:35:45: Thread ***First: ending update
14:35:45: Thread ***Third: starting update
14:35:45: Thread ***Second has locked / local_copy(1)
14:35:45: Thread ***Second has unlocked / local_copy(2)
14:35:45: Thread ***Second: ending update
14:35:45: Thread ***Third has locked / local_copy(2)
14:35:45: Thread ***Third has unlocked / local_copy(3)
14:35:45: Thread ***Third: ending update
14:35:45: Testing *** . Ending value is (3)
'Python > Advanced' 카테고리의 다른 글
[Python] Multiprocessing(1) - Join, is_alive (0) | 2021.05.17 |
---|---|
[Python] Thread(5) - Producer and Consumer Using Queue (0) | 2021.05.17 |
[Python] Thread(3) - ThreadPoolExecutor (0) | 2021.05.14 |
[Python] Thread(2) - DeamonThread (0) | 2021.05.14 |
[Python] Thread(1) - Basic (0) | 2021.05.14 |