线程

作者: 木叶苍蓝 | 来源:发表于2020-04-18 16:55 被阅读0次

    python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装,可以更加方便的使用。

    1、使用threading模块
    多线程执行
    #coding=utf-8
    import time
    
    def sey_sorry():
        print("亲爱的,我错了,我能吃饭吗?")
        time.sleep(1)
    
    if __name__ == "__main__":
        for i in range(5):
            t = threaeding.Thread(target=say_sorry)
            t.start()
    
    多线程执行多个函数
    #coding=utf-8
    import time
    import threading
    
    def sing():
        for i in range(5):
            print("-------唱歌--------")
            time.sleep(1)
    
    def dance():
        for i in range(5):
            print("--------跳舞---------")
            time.sleep(1)
    
    def main():
        t1 = threading.Thread(target=sing)
        t2 = threading.Thread(target=dance)
        t1.start()
        t2.start()
    
    if __name__ == "__main__":
        main()
    
    查看线程数量
    #coding=utf-8
    import time
    import threading
    
    def sing()
        for i in range(5):
            print("正在唱歌...")
            time.sleep(1)
    
    def dance():
        for i in range(5):
            print("正在跳舞...")
            time.sleep(1)
    
    if __name__ == "__main__":
        print("------开始-----: %s"%(time.ctime(),))
        t1 = threading.Thread(target=sing)
        t2 = threading.Thread(target=dance)
        t1.start()
        t2.start()
        
        while True:
            length = len(threading.enumerate())
            print("当前运行线程数量: %s"%(length,))
            if length <= 1:
                break
            time.sleep(0.5)
    
    线程执行代码的封装

    通过使用threading模块能完成多任务的程序开发,为了让每个线程的封装性更完美,所以使用threading模块时,往往会定义一个新的子类class,只要继承threading.Thread就可以了,然后重写run方法。

    #coding:=utf-8
    import time
    import threading
    
    class MyThread(threading.Thread):
        def run(self):
            for i in range(3):
                time.sleep(1)
                msg = "I'm "+self.name+"@" +str(i)
                print(msg)
            self.login()
            self.register()
        def login(self):
            pass
        def register(self):
            pass
    if __name__ == "__main__":
        t = MyThread()
        t.start()
    
    多线程-共享全局变量
    #coding=utf-8
    import time
    from threading import Thread
    
    g_num = 100
    
    def work1():
        global g_num
        for i in range(3):
            g_num += 1
        print("----in work1, g_num is %d-----"%(g_num,))
    
    def work2():
        global g_num
        print("---in work2, g_num is %d-----"%(g_num,))
    
    print("-----线程创建之前g_num is %d----"%(g_num,))
    t1= Threaed(target=work1)
    t1.start()
    time.sleep(1)
    t2 = Thread(target=work2)
    t2.satrt()
    
    多线程传参
    #coding=utf-8
    import ime
    import threading
    
    def test1(temp):
        temp.append(33)
        print("----in test1 temp = %s----"%(str(temp),))
    def test2(temp):
        print("---in test2 temp = %s----"%(str(temp),))
    
    g_nums = [11, 22]
    
    def main():
        # target 指定要执行的线程
        # args 指定函数传递参数
        t1 = threaeding.Thread(target=test1, args=(g_nums,))
        t2 = threaeding.Thread(target=test2, args=(g_nums,))
        t1.start()
        time.slee(1)
        t2.start()
        time.sleep(1)
        print("----in main Thread g_nums = %s----"%(g_nums,))
    if __nam__ == "__main__":
        main()
    
    多线程-共享全局变量问题

    假如两个线程t1和t2都要对全局变量g_num=0进行加1运算,t1和t2都各对g_num加10次,g_num的最终结果应该是20。
    但是由于是多线程同时操作,有可能出现下面情况:

    1. 在g_num=0时,t1取得g_num=0。此时系统把t1调度为'sleeping'状态,把t2调度为'runing'状态。t2也获得g_num=0。
    2. 然后t2对得到的g_num进行加1并赋值给g_num,使得g_num=1。
    3. 然后系统有把t2调度为'sleeping',把t1转为'runing',此时t1又把之前得到的g_num=0进行加1赋值给g_num。
    4. 虽然t1和t2都对g_num加1,但是g_num最后的结果还是1。
      这里就要加互斥锁来解决这个问题
    # 创建锁
    mutex = threading.Lock()
    # 加锁
    mutex.acquire()
    # 解锁
    mutex.release()
    

    注意:

    • 如果这个锁之前是没有上锁的,那么acquire不会阻塞
    • 如果在调用acquire对这个锁上锁之前它已经被其他线程加锁了,那么此时acquire会阻塞,直到这个锁被解锁为止。
    #coding=utf-8
    # 使用互斥锁完成2个线程对同一个全局变量各加100万次
    import time
    import threading
    
    g_num = 0
    
    def test1(num):
        global g_num
        for i in range(num):
            mutex.acquire() # 上锁
            g_num += 1
           mutex.release() # 解锁
        print("----test1---g_num=%d"%(g_num,))
    
    def test2(num):
        global g_num
        for i in range(num):
            mutex.acquire() # 上锁
            g_num += 1
            mutex.release() # 解锁
        print("----test2---g_num=%d"%(g_num,))
    
    # 创建一个互斥锁
    # 默认是未上锁状态
    mutex = threading.Lock()
    def main():
        t1 = threading.Thread(target=test1, args=(1000000, ))
        t2 = threading.Thread(target=test2, args=(1000000, ))
      
        t1.start()
        t2.start()
    
        # 等待上面2个线程执行完毕...
        time.sleep(2)
        print("---in main Thread g_num = %d----"%(g_num,))
    
    if __nam__ == "__main__":
        main()
    
    死锁

    在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
    尽管死锁很少发生,一旦发生就会造成应用的停止响应。

    #coding=utf-8
    import time
    import threaeding
    
    class MyThreaed(threading.Thread):
        def run(self):
            # 对mutexA上锁
            mutexA.acquire()
            # mutexA上锁后,延迟1秒,等待另一个线程对mutexB上锁
            print(self.name + "----do 1 -- up ---")
             time.sleep(1)
    
            # 此时会阻塞,因为这个mutexB已经被另外一个线程抢先上锁了
            mutexB.acquire()
            print(self.name+"----do1---down----")
            mutexB.release()
    
            # mutexA解锁
            mutexA.release()
    
    class MyThread2(threading.Thread):
        def run(self):
            # 对 mutexB上锁
            mutexB.acquire()
    
            # mutexB上锁后,延迟1秒,等待另外线程把mutexA上锁
            print(self.name+"------do2-----up----")
            time.sleep(1)
    
            # 此时会阻塞,因为这个mutexA已经被另外线程上锁了
            mutexA.acquirt()
            print(self,name+"----do2------down------")
            mutexA.release()
    
            # mutexB解锁
            mutexB.release()
    
    mutexA = threading.Lock()
    mutexB = threading.Lock()
    
    if __name__ == "__main__": 
        t1 = MyThread1()
        t2 = MyThread2()
    
        t1.start()
        t2.start()
    

    相关文章

      网友评论

          本文标题:线程

          本文链接:https://www.haomeiwen.com/subject/zvqbvhtx.html