day18 요약: 다중 스레드(2019-05-09)

5805 단어
1. 스레드(thread)
  • 모든 프로세스는 기본적으로 하나의 라인이 있습니다. 이 라인을 주 라인이라고 하고 다른 프로세스는 하위 라인
  • 이라고 합니다.
    2. 스레드 모듈(threading)
  • threading 모듈의 Thread 클래스를 이용하여 서브스레드 만들기
  • 1)threading 모듈
  • 스레드 관련 특수 기능 제공
  • import threading

  • 2)current_thread 함수
  • 현재 스레드 가져오기
  • print(threading.current_thread())

  • 3) Thread 클래스
  • Thread 클래스의 대상은 라인이기 때문에 하위 라인이 필요하면 이 클래스를 만드는 대상
  • Thread(target,args,kwargs) target: 함수, 현재 생성된 서브라인에서 호출해야 하는 함수args/kwargs: target의 함수를 호출하기 위해 필요한 실참 목록
  • 스레드 생성 대상: t1 =threading.Thread(target=download,args=('복연5',)
  • 4) start 방법
  • 하위 라인의 작업을 시작합니다. 라인 대상입니다.start()
  • start 방법을 통해 하위 라인에서 target에 대응하는 함수를 호출
  • t1.start()

  • 5) 인스턴스
    import time
    from datetime import datetime
    import threading  #             
    
    def download(film_name):
        print('    : %s' % film_name, datetime.now())
        time.sleep(5)
        print('%s    ' % film_name, datetime.now())
    
    print(threading.current_thread()) #        ,   
    
    # a.      
    t1 = threading.Thread(target=download, args=('  5',))
    # t1 = threading.Thread(target=download, kwargs={'film_name': '  5'})
    t2 = threading.Thread(target=download, args=('007',))
    
    # b.           
    t1.start()
    t2.start()
    

    3. 자신의 라인 클래스 만들기
  • 주의: 한 프로세스에 여러 개의 라인이 있으면 프로그램은 모든 라인이 끝날 때 끝납니다. 이상 붕괴가 발생하면 사실은 라인이 무너지고 그 중 한 라인이 붕괴되면 다른 라인의 운행에 영향을 주지 않습니다
  • 1) 클래스 상속 선언Thread
  • class DownloadThread(Thread):

  • 2)run 구현 방법
  • 이 방법의 임무는 하위 라인에서 실행해야 하는 임무
  • 3) 하위 클래스로 직접 스레드 객체 만들기
  • t1 = DownloadThread('복연4')
  • 4) start를 통해 하위 스레드의 작업 수행
  • t1.start (): start 방법만 서브스레드 작업 실행run의 내용을 열 수 있습니다
  • t1.run (): 런 방법을 직접 호출할 수 없습니다. 이 호출 결과는 주 라인에서run의 내용을 실행하는 것이지 하위 라인
  • 이 아니기 때문입니다.
    5) 인스턴스 1
    from threading import *
    import time
    from datetime import datetime
    
    class DownloadThread(Thread):
        def __init__(self, film_name):
            super().__init__()
            self.film_name = film_name
    
        def run(self):
            print('    : %s' % self.film_name, datetime.now())
            time.sleep(6)
            print('    : %s' % self.film_name, datetime.now())
    
    #            
    t1 = DownloadThread('  4')
    t2 = DownloadThread('  7 ')
    #   start          
    t1.start()
    t2.start()
    # t1.run()    #       run  ,                 
    

    6) 실례2: 서버의 다중 루틴 기능 실현
    from socket import *
    from threading import *
    
    
    class ChatThread(Thread):
        def __init__(self, connect: socket, address):
            super().__init__()
            self.connect = connect
            self.address = address
    
        def run(self):
            while True:
                self.connect.send('  ,    !'.encode())
    
                message = self.connect.recv(1024)
                print('%s:%s' % (self.address[0], message.decode(encoding='utf-8')))
    
            connect.close()
    
    
    server = socket()
    server.bind(('10.7.185.82', 8888))
    server.listen(512)
    while True:
        #     
        connect, address = server.accept()
    
        #            ,   
        t = ChatThread(connect, address)
        t.start()
    

    4.join 방법
  • 어떤 임무가 어떤 라인이 끝난 후에야 실행되기를 원한다면 이 임무의 코드를 해당 라인 대상에 대한join 방법을 호출하는 뒤에 두기
  • 인스턴스
  • from threading import Thread
    from datetime import datetime
    import time
    from random import randint
    
    
    class DownloadThread(Thread):
        def __init__(self, name, time):
            super().__init__()
            self.name = name
            self.time = time
    
        def run(self):
            print('    :%s' % self.name)
            time.sleep(self.time)
            print('    :%s' % self.name)
    
    
    t1 = DownloadThread('     ', 3)
    t2 = DownloadThread('    ', 2)
    
    t2.start()
    t1.start()
    
    t1.join()
    t2.join()
    print('    ')
    
    print('=============================')
    t1 = DownloadThread('     ', 3)
    t2 = DownloadThread('    ', 2)
    t2.start()
    t2.join()
    t1.start()
    

    5. 잠금 사용(Lock)
    1) 질문
  • 여러 라인이 한 데이터를 동시에 읽기와 쓰기를 하면 한 라인이 데이터를 읽자마자 미처 쓰지 못하고 다른 라인이 읽기 작업을 하는 데이터 안전 문제가 발생할 수 있다.(여러 사람이 한 화장실에 갔는데 한 사람이 들어가도 나오지 않고 다른 사람이 또 들어가는 문제)
  • 2) 문제 해결: 잠금
  • 각 데이터가 잠금 개체에 해당하도록 보장
  • 조작 데이터 앞 잠금, 데이터 조작 완료 후 잠금 해제
  • 3) 인스턴스 1
    import time
    from threading import Thread, Lock
    
    class Account:
        def __init__(self, name, tel, balance=50):
            self.name = name
            self.tel = tel
            self.balance = balance
            #        
            self.lock = Lock()
    
        def save_money(self, money):
            print('    ')
            #   
            self.lock.acquire()
            value = self.balance
            time.sleep(4)
            self.balance = value+money
            print('    : %.2f' % self.balance)
            #    
            self.lock.release()
    
        def draw_money(self, money):
            print('    ')
            #   
            self.lock.acquire()
            value = self.balance
            time.sleep(5)
            if value < money:
                print('    !    ')
                return
            self.balance = value - money
            print('    :%.2f' % self.balance)
            #    
            self.lock.release()
    
    
    acount = Account('  ', '15300022703', 10000)
    
    #        
    t1 = Thread(target=acount.save_money, args=(1000,))
    #        
    t2 = Thread(target=acount.draw_money, args=(500,))
    
    t1.start()
    t2.start()
    

    4) 인스턴스 2
    import time
    from threading import Thread, Lock
    
    share_data = 1000
    lock = Lock()
    
    def add_data(value):
        lock.acquire()
        global share_data
        old_data = share_data
        time.sleep(4)
        share_data = old_data + value
        lock.release()
    
    t1 = Thread(target=add_data, args=(200,))
    t2 = Thread(target=add_data, args=(300,))
    t1.start()
    t2.start()
    
    t1.join()
    t2.join()
    
    print(share_data)
    

    좋은 웹페이지 즐겨찾기