2020년 8월 23일 일요일

Thread event in python

앞에서 Thread 동기화를 위한 임계 영역(Critical section)사용에 대한 내용을 다루었습니다. 
이번에는 Event에 대해서 설명하도록 하겠습니다. Event는 두개 이상의 thread가 한쪽의 작업이 끝났는지 기다리는 용도로 사용합니다. 만약 Event기능이 없다면 한쪽 thread에서는 특정 변수값이 변화가 생기는지 조건문을 이용해서 계속 검사 하도록 구현을 해야합니다. 이렇게 되면 CPU 자원을 소모하게 됩니다. 


먼저 event 없이 구현했을때 아래와 같은 방식으로 구현됩니다.
import time
import datetime
import threading
account_balance = 0
tevent = 0

def wait_for_event():
	global tevent
	"""Wait for the event to be set before doing anything"""
	print(datetime.datetime.now(),'wait_for_event: starting')
	while True:
		if tevent == 1:
			break
	print(datetime.datetime.now(),'wait_for_event: end')


def change_account_balance(delta):
	wait_for_event()
	global account_balance
	account_balance -= delta
	print("+",threading.currentThread().getName(),account_balance)
	account_balance += delta
	print("-",threading.currentThread().getName(),account_balance)

thread1 = threading.Thread(target=change_account_balance, args=(20,))
thread1.start()
thread2 = threading.Thread(target=change_account_balance, args=(10,))
thread2.start()

print(datetime.datetime.now(),"sleep")
time.sleep(3)
print(datetime.datetime.now(),"sleep out")
tevent = 1

thread1.join()
thread2.join()

동작 설명
main thread에서 3초 기다린 후(time.sleep(3)) thread를 동작 시키기 위한 코드 입니다.
전역 변수를 이용해서 값이 변경되기를 기다리게 됩니다. 이렇게 되면 CPU자원을 계속 소모하게 됩니다.

실행 화면
2020-08-23 08:26:49.402400 wait_for_event: starting
2020-08-23 08:26:49.411379 wait_for_event: starting
2020-08-23 08:26:49.423345 sleep
2020-08-23 08:26:52.460225 sleep out
2020-08-23 08:26:52.466207 wait_for_event: end
+ Thread-2 -10
2020-08-23 08:26:52.466207 wait_for_event: end
- Thread-2 0
+ Thread-1 -20
- Thread-1 0


아래는 Event 사용 예제입니다.
1. Event() 변수 정의
2. 기다리는 곳에서는 wait() 사용
3. 명령을 주는곳에서는 set() 사용

import time
import datetime
import threading
account_balance = 0
account_balance_lock = threading.Lock()
tevent = threading.Event()
# wait() is_set() set()

def wait_for_event(e):
	"""Wait for the event to be set before doing anything"""
	print(datetime.datetime.now(),'wait_for_event: starting')
	e.wait()
	print(datetime.datetime.now(),'wait_for_event: e.is_set()->', e.is_set())

def wait_for_event_timeout(e, t):
	"""Wait t seconds and then timeout"""
	print(datetime.datetime.now(),'wait_for_event_timeout: starting')
	e.wait(t)
	print(datetime.datetime.now(),'wait_for_event_timeout: e.is_set()->', e.is_set())

def change_account_balance(e, delta):
	wait_for_event_timeout(e,10)
	global account_balance
	account_balance -= delta
	print("+",threading.currentThread().getName(),account_balance)
	account_balance += delta
	print("-",threading.currentThread().getName(),account_balance)

thread1 = threading.Thread(target=change_account_balance, args=(tevent,20))
thread1.start()
thread2 = threading.Thread(target=change_account_balance, args=(tevent,10))
thread2.start()

print(datetime.datetime.now(),"sleep")
time.sleep(3)
print(datetime.datetime.now(),"sleep out")
tevent.set()

thread1.join()
thread2.join()

wait()함수 호출시 시간을 설정가능합니다.

실행화면
처음 예제와 거의 동일합니다.
2020-08-23 08:32:13.383186 wait_for_event_timeout: starting
2020-08-23 08:32:13.386177 wait_for_event_timeout: starting
2020-08-23 08:32:13.386177 sleep
2020-08-23 08:32:16.388159 sleep out
2020-08-23 08:32:16.388159 wait_for_event_timeout: e.is_set()-> True
2020-08-23 08:32:16.388159 wait_for_event_timeout: e.is_set()-> True
+ Thread-1 -20
+ Thread-2 -30
- Thread-2 0
- Thread-1 -10





댓글 없음:

댓글 쓰기