본문 바로가기

Python/Advanced

[Python] Thread(4) - Lock, Unlock

공유자원을 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)