python thread

kangjuju·2023년 4월 17일
0

python

목록 보기
4/4
  • thread : light weight process라고도 함
  • process 내에서 수행되며 같은 실행단위를 공유
  • multi thread로 multi tasking에 효과를 볼 수 있다. (병렬처리)
  • 네트워크 등의 작업에 많이 쓰이고 있다.

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사용시 스레드가 끝날때까지 메인스레드가 대기를 한다.


thread로 시간 출력

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('프로그램 종료')

thread 공유자원

  • 전역변수는 스레드의 공유자원이 된다.
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을 해제

또다른 방법(예제)

  • 이번에는 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('장사끝')

0개의 댓글