python-thread

파이썬 - 다중 스레드
  • 멀티스레드 멀티스레드란 여러 프로그램을 동시에 실행하는 것과 유사하며 벽돌을 옮기는 것과 같다. 순서가 없고 멀티스레드 운행은 다음과 같은 장점이 있다.
  • 라인을 사용하면 장시간을 차지하는 프로그램의 작업을 백엔드에서 처리할 수 있다.
  • 사용자 인터페이스는 더욱 사람을 끌어당길 수 있다. 예를 들어 사용자가 단추를 누르면 특정 이벤트의 처리를 촉발하고 처리의 진도를 표시할 수 있다
  • 프로그램의 실행 속도가 빨라질 수 있음
  • 사용자 입력, 파일 읽기와 쓰기, 인터넷 수신 데이터 등 대기 작업의 실현에 있어 라인이 비교적 유용하다.이런 상황에서 우리는 메모리 점용 등 귀중한 자원을 방출할 수 있다.

  • 모든 스레드에는 그 자신의 CPU 레지스터가 있는데, 스레드의 상하문이라고 하는데, 이 상하문은 스레드가 지난번에 이 스레드를 실행한 CPU 레지스터의 상태를 반영한다.명령 포인터와 창고 포인터 레지스터는 라인 상하문에서 가장 중요한 두 개의 레지스터입니다. 라인은 항상 프로세스가 상하문에서 실행됩니다. 이 주소들은 라인이 있는 프로세스 주소 공간의 메모리를 표시하는 데 사용됩니다.
    Python의 표준 라이브러리는 두 개의 모듈을 제공합니다:thread와 threading,thread는 저급 모듈,threading은 고급 모듈,맞아thread가 봉인되었습니다.절대 다수의 상황에서 우리는threading이라는 고급 모듈만 사용할 수 있다.모든 프로세스가 기본적으로 하나의 라인을 시작하기 때문에, 우리는 이 라인을 주 라인이라고 부르고, 주 라인은 새로운 라인을 시작할 수 있습니다. Python의threading 모듈에currentthread () 함수, 현재 라인의 실례를 영원히 되돌려줍니다.주 루틴 실례의 이름은MainThread입니다. 하위 루틴의 이름은 만들 때 지정됩니다. 이름이 없으면 자동으로 루틴에Thread-1,Thread-2,threading은 루틴과 관련된 작업을 제공하는 데 사용됩니다. 루틴은 응용 프로그램에서 작업하는 가장 작은 단원입니다.python 현재 버전의 다중 루틴 라이브러리는 우선순위, 루틴 그룹을 실현하지 못했고, 루틴도 정지, 정지, 복구, 중단될 수 없습니다.threading 모듈에서 제공하는 클래스: Thread, Lock, Rlock, Condition, [Bounded] Semaphore, Event, Timer, local.threading 모듈에서 제공하는 상수:threading.TIMEOUT_MAX는 threading 글로벌 제한 시간을 설정합니다.
  • 라인을 여는 두 가지 방식 (1) 함수
    import threading
    import time
    
    def action(n):
        time.sleep(1)
        print('    :{0}'.format(threading.current_thread()))
        print('i am action',n)
        print('my name is ',n)
    
    for i in range(10):
        t=threading.Thread(target=action,args=(i,))
        t.start()
    
    if __name__=='__main__':
        print(threading.current_thread())
        print('main thread end')
    
    (2) 클래스로 라인 대상을 포장
    class MyThread(threading.Thread):
        def __init__(self,arg):
            super(MyThread,self).__init__()    #  :                。
            self.arg=arg
        def run(self):         #            
            time.sleep(1)
            print('the arg is:%s\r' % self.arg)
    
    for i in range(4):
        t=MyThread(i)
        t.start()
    
  • Thread 클래스
  • 구조 방법: Thread(group=None, targe=None,name=None,args=(), kwargs={} 그룹: 스레드 그룹, 아직 실현되지 않았습니다. 라이브러리 인용에서 힌트는 반드시 None이어야 합니다.target: 실행할 방법;name: 라인 이름;args/kwargs: 입력할 방법의 매개 변수입니다.
  • 인스턴스 메서드: isAlive(): 반환 스레드가 실행 중인지 여부.실행 중은 시작 후, 종료 전입니다.get/setName(name): 스레드 이름을 가져오거나 설정합니다.start (): 스레드가 준비되었습니다. CPU 스케줄링join ([timeout]) 을 기다리십시오. 현재 상하문 환경의 스레드를 막습니다. 이 방법의 스레드가 종료되거나 지정한 timeout (선택할 수 있는 인자) 에 도착할 때까지.

  • threading 모듈에서 일반적으로 사용하는 방법:
  • threading.currentThread(): 현재 스레드 변수를 반환합니다.
  • threading.enumerate (): 실행 중인 라인을 포함하는list를 되돌려줍니다.실행 중인 스레드는 시작 후, 종료 전, 시작 전과 종료 후의 스레드를 포함하지 않습니다.
  • threading.activeCount (): 실행 중인 라인의 수를 되돌려줍니다. 렌 (threading.enumerate () 과 같은 결과를 가져옵니다.

  • 백엔드 스레드와 백엔드 스레드 is/setDaemon(bool): 백엔드 스레드를 가져오거나 설정합니다(기본 백엔드 스레드(False)).(start 전에 설정)
  • 백그라운드 스레드라면 메인 스레드 실행 과정에서 백그라운드 스레드도 진행되고 메인 스레드가 실행된 후 백그라운드 스레드는 성공 여부와 상관없이 메인 스레드와 백그라운드 스레드가 모두 정지된다
  • 만약에 프론트 데스크톱의 라인이라면 메인 라인의 집행 과정에서 프론트 데스크톱의 라인도 진행되고 메인 라인의 집행이 끝난 후에 프론트 데스크톱의 라인도 집행이 끝나면 프로그램이 정지된다
  • if __name__=='__main__':
    for i in range(4):
        t=MyThread(i)
        t.setDaemon(True)
        t.start()
    print('main thread end')
    
  • 막기-join join () 현재 상하문 환경의 루트를 막습니다. 이 방법을 호출한 루트가 종료되거나 지정한timeout에 도착할 때까지 setDeamon (True) 주 루트가 설정되어 있어도 하위 루트가 끝날 때까지 기다립니다.라인은 start () 를 먼저 하고 Join () 을 눌러야 합니다.
    if __name__ == '__main__':
        for i in range(4):
            t = MyThread(i)
            t.start()
            t.join()
    
    이를 통해 알 수 있듯이 프로그램은 순서대로만 실행할 수 있고 모든 라인이 이전 라인의join에 의해 막혀서'다라인'은 다라인의 의미를 잃었다.
    올바른 방법
    if __name__ == '__main__':
        th=[]
        for i in range(4):
            t = MyThread(i)
            th.append(t)
            t.start()
        for tt in th:
            tt.join()
        #  join  ,                       ,      
        print('main thread end!')
    
  • 스레드 동기화 - Lock, Rlock 클래스는 스레드 간에 임의로 스케줄링됨: 어떤 스레드가 n개를 실행한 후에 CPU가 이어서 다른 스레드를 실행할 수 있습니다.여러 라인이 한 메모리의 자원을 동시에 조작할 때 혼란을 일으키지 않도록 자물쇠를 사용합니다.Lock은 사용 가능한 최하위 동기화 명령입니다.Lock이 잠겨 있으면 특정 스레드에 의해 소유되지 않습니다.Lock에는 잠금 및 비잠금 두 가지 상태와 두 가지 기본 방법이 있습니다.Lock에 잠금 탱크가 있다고 볼 수 있습니다. 노드가 잠금을 요청할 때, 노드를 탱크에서 잠금된 후에 풀을 나갈 때까지 연결합니다.연못의 라인이 상태도에서 동기적으로 막힌 상태에 있습니다.RLock은 같은 스레드에서 여러 번 요청할 수 있는 동기화 명령입니다.RLock은'가진 스레드'와'귀속 레벨'이라는 개념을 사용하며 잠긴 상태일 때 RLock은 어떤 스레드에 의해 보유된다.RLock이 있는 스레드는 acquire()를 다시 호출할 수 있으며 잠금을 풀 때 release()를 같은 횟수로 호출해야 합니다.RLock에는 acquire ()/release () 가 성공적으로 호출될 때마다 카운터가 +1/-1, 0일 때 잠기지 않은 상태로 잠겨 있다고 볼 수 있습니다.인스턴스 메서드:
  • acquire([timeout]): 잠금을 시도합니다.스레드를 동기 막힘 상태로 진입시키다.
  • release(): 자물쇠를 방출합니다.사용 전 라인은 반드시 잠금을 받아야 합니다. 그렇지 않으면 이상이 발생합니다.
  • import threading
    import time
    
    count=0
    lock=threading.RLock()
    def action(arg):
        lock.acquire()
        time.sleep(1)
        global count
        count+=1
        print(threading.current_thread())
        count-=1
        print('the arg is:{0}.count is:{1}'.format(arg,count))
        lock.release()
    
    ths=[]
    for i in range(4):
        t=threading.Thread(target=action,args=(i,))
        ths.append(t)
    
    for tt in ths:
        tt.start()
    
    for tt in ths:
        tt.join()
    
    if __name__=='__main__':
        print('main thread end')
    
  • Lock 대비 RLock
  • #Lock
    lock.acquire()
    lock.acquire()  #     。              
    
    #Rlock
    rLock.acquire()
    rLock.acquire() #      ,      。
    
  • Condition 클래스 Condition(조건 변수)은 일반적으로 잠금장치와 연관됩니다.여러 Contidion에서 자물쇠를 공유해야 할 때, 구성 방법에 Lock/RLock 실례를 전달할 수 있으며, 그렇지 않으면 스스로 RLock 실례를 생성할 수 있습니다.

  • Lock이 가지고 있는 잠금 탱크를 제외하고 Condition에는 대기 탱크가 포함되어 있으며, 탱크의 루트는 다른 루트가 notify ()/notify All () 알림을 호출할 때까지 대기 막힌 상태라고 볼 수 있습니다.알림을 받은 후 라인이 잠금탱크에 들어가 잠금을 기다립니다.구성 방법: Condition([lock/rlock]) 인스턴스 방법:
  • acquire([timeout])/release(): 관련 자물쇠를 호출하는 상응하는 방법.
  • wait([timeout]): 이 방법을 사용하면 컨디션의 대기 탱크에 들어가서 알림을 기다리고 자물쇠를 풀 수 있습니다.사용 전 라인은 반드시 잠금을 받아야 합니다. 그렇지 않으면 이상이 발생합니다.
  • notify(): 이 방법을 사용하면 대기 탱크에서 하나의 라인을 선택하고 알림을 받습니다. 알림을 받은 라인은 acquire()를 자동으로 호출하여 잠금(잠금 탱크에 들어가기)을 시도합니다.다른 라인은 여전히 연못을 기다리고 있다.이 방법을 사용하면 잠금이 풀리지 않습니다.사용 전 라인은 반드시 잠금을 받아야 합니다. 그렇지 않으면 이상이 발생합니다.
  • notifyAll (): 이 방법을 사용하면 대기 탱크의 모든 루트를 알립니다. 이 루트는 잠금 탱크에 들어가서 잠금을 시도합니다.이 방법을 사용하면 잠금이 풀리지 않습니다.사용 전 라인은 반드시 잠금을 받아야 합니다. 그렇지 않으면 이상이 발생합니다.
  • import threading
    import time
    
    product=None
    con=threading.Condition()
    
    #     
    def product():
        global product
        if con.acquire():
            while True:
                if not product:
                    print('product...')
                    product='anything'
                    #     ,      
                    con.notify()
                #    
                con.wait()
                time.sleep(2)
    
    #     
    def consume():
        global product
        if con.acquire():
            while True:
                if product:
                    print('consume...')
                    product=None
                    #     ,      
                    con.notify()
                #    
                con.wait()
                time.sleep(2)
    
    t1=threading.Thread(target=product)
    t2=threading.Thread(target=consume)
    t2.start()
    t1.start()
    
    생산자 소비자 모델
    import threading
    import time
    
    condition=threading.Condition()
    products=0
    
    class Producer(threading.Thread):
        def run(self):
            global products
            while True:
                if condition.acquire():
                    if products<10:
                        products+=1
                        print("Producer(%s):deliver one,now products:%s"%(self.name,products))
                        condition.notify()
                        condition.release()
                    else:
                        print("Producer(%s):already 10, stop deliver, now products:%s" % (self.name, products))
                        condition.wait()
                    time.sleep(2)
    
    class Consumer(threading.Thread):
        def run(self):
            global products
            while True:
                if condition.acquire():
                    if products>1:
                        products-=1
                        print("Consumer(%s):consume one, now products:%s" % (self.name, products))
                        condition.notify()
                        condition.release()
                    else:
                        print("Consumer(%s):only 1, stop consume, products:%s" % (self.name, products))
                        condition.wait()
                    time.sleep(2)
    
    if __name__=="__main__":
        for p in range(0,2):
            p=Producer()
            p.start()
    
        for c in range(0,3):
            c=Consumer()
            c.start()
    
    condition.notifyAll()
    import threading
    
    alist=None
    condition=threading.Condition()
    
    def doGreate():   #            
        global alist
        if condition.acquire():
            if not alist:
                alist=[0 for i in range(10)]
                condition.notifyAll()
            condition.release()
    
    def doPrint():    #               
        if condition.acquire():
            while not alist:
                condition.wait()
            for i in alist:
                print(i)
    
            print()
            condition.notify()
            condition.release()
    
    def doSet():     #                   
        if condition.acquire():
            while not alist:
                condition.wait()
            for i in range(len(alist))[::-1]:
                alist[i]=1
                print(alist[i])
            condition.notify()
            condition.release()
    
    tcreate=threading.Thread(target=doGreate,name='tcreate')
    tprint=threading.Thread(target=doPrint,name='tprint')
    tset=threading.Thread(target=doSet,name='tset')
    tcreate.start()
    tprint.start()
    tset.start()
    

    좋은 웹페이지 즐겨찾기