thread
- 확인용 for문을 생성했다. 1~50까지 출력함
def run(id):
for i in range(1,51):
print('id :{0}-->{1}'.format(id,i))
여기서 thread를 사용하지 않은경우.
#thread를 사용하지 않은 경우 순차처리
run(1)
run(2)
두 함수가 기본적으로 순차적으로 처리하는 것을 알 수 있다.
이제 thread를 사용하여 병렬처리를 해보자
threading.Thread(target=실행함수,args=...)
스레드 대상함수와 넘길 인자를 작성한다.
th1 = threading.Thread(target=run,args=('일',))
th2 = threading.Thread(target=run,args=('둘',))
th1.start() #thread 대상함수 지정 후 실행.
th2.start()
th1.join() #사용자 스레드가 종료 될때까지 메인스레드의 대기를 요청.
th2.join()
print('프로그램 종료') #메인 스레드
두 함수가 병렬처리 되는것을 확인했다. 이는 스케줄러에 의해 랜덤처리 되므로 순서를 정할 수는 없다. 프로세스의 작은 실행 단위 이므로 메인스레드가 끝나더라도 스레드가 끝나야 프로그램이 종료 된다.
join사용시 스레드가 끝날때까지 메인스레드가 대기를 한다.
import time
import threading
def show_data():
now = time.localtime()
print('현재는 {}월 {}일 {}시 {}분 {}초'.format(now.tm_mon,now.tm_mday,\
now.tm_hour,now.tm_min,now.tm_sec))
def myrun():
while True:
now2 = time.localtime()
if now2.tm_min == 27:break
show_data()
time.sleep(1)
th = threading.Thread(target=myrun)
th.start()
th.join()
print('프로그램 종료')
import threading,time
g_count = 0 # 전역변수는 스레드의 공유자원이 됨
lock = threading.Lock() #<=======
def threadCount(id,count):
global g_count
for i in range(count):
lock.acquire() #<======
print('id %s ==> count: %s, g_count:%s'%(id,i,g_count))
g_count+=1
lock.release() #<======
for i in range(1,5):
threading.Thread(target=threadCount,args=(i,5)).start()
time.sleep(2)
print('최종 g_count : ',g_count) #출력 25
print('프로그램 종료')
병렬처리를 하며 자연스레 전역변수를 서로 공유하면서 충돌이 일어난다.
이러한 충돌방지하기 위해 전역변수를 한 스레드가 점유 할 수 있도록
나머지 스레드를 비활성화하는 동기화 작업이 있다.
lock = threading.Lock()
: lockclass객체 생성 lock.acquire()
:현재 스레드가 공유자원을 처리하는 동안 다른 스레드 대기(lock)lock.release()
: 작업이 끝나면 lock을 해제Condition()
함수가 담당했다.import threading,time
bread_plate = 0 #빵 접시 : 공유 자원
lock = threading.Condition() #lock을 위한 조건 변수
class Maker(threading.Thread): #빵 생산자 class
def run(self):
global bread_plate
for i in range(1,31):
lock.acquire() #공유자원 충돌 방지
while bread_plate >= 10: #접시는 10개 제한
print('빵 제한초과(10)로 생산 대기')
lock.wait() #스레드 비활성화
bread_plate += 1
print('빵 생산 : ',bread_plate)
lock.notify() #스레드 활성화
lock.release() #lock 해제
class Consumer(threading.Thread): #빵 소비자 class
def run(self):
global bread_plate
for i in range(1,31):
lock.acquire() #공유자원 충돌 방지
while bread_plate < 1: #접시는 10개 제한
print('빵이 모두 소진. 대기')
lock.wait() #스레드 비활성화
bread_plate -= 1
print('빵 소비 : ',bread_plate)
lock.notify() #스레드 활성화
lock.release() #lock 해제
mak = []; con=[]
for i in range(1,6): #생산자 수 6명
mak.append(Maker())
for i in range(1,6): #소비자 수 6명
con.append(Consumer())
for th1 in mak:
th1.start()
for th2 in con:
th2.start()
for th1 in mak:
th1.join()
for th2 in con:
th2.join()
print('장사끝')