zoukankan      html  css  js  c++  java
  • Day036--Python--线程

    1. 线程

      

    from threading import Thread
    
    def func(n):
        print(n)
    
    if __name__ == '__main__':
        t = Thread(target=func, args=(3,))
        t.start()
        print('主线程结束')
    View Code创建进程方法一
    from threading import Thread
    
    class MyThread(Thread):
        def run(self):
            print('XXX')
    
    if __name__ == '__main__':
        t = MyThread()
        t.start()
        print('主线程结束')
    View Code创建进程方法二

    2. 线程和进程的效率对比

      线程的效率非常高, 而且线程的开启不需要消耗资源

    import time
    from threading import Thread
    from multiprocessing import Process
    
    def func(n):
        num = 0
        for n1 in range(n):    # 做个运算, 消耗一下时间, 好比较线程与进程的效率
            num += n1
        print('num', num)
    
    if __name__ == '__main__':
        t_s_t = time.time()   # 线程运行起始时间
        tlst = []
        for i in range(10):
            t = Thread(target=func, args=(10,))
            t.start()
            tlst.append(t)
        [t.join() for t in tlst]   # 迭代着join等待线程全部运行完毕
        t_e_t = time.time()      # 线程运行结束时间
        t_dif_t = t_e_t - t_s_t   # 计算线程的运行时间差
        
        print('线程的结束时间', t_dif_t)
        p_s_t = time.time()
        plst = []
        for i in range(10):
            p = Process(target=func, args=(10,))
            p.start()
            plst.append(p)
        [p.join() for p in plst]
    
        p_e_t = time.time()
        p_dif_time = p_e_t - p_s_t
        print('进程的结束时间', p_dif_time)
        print('主线程结束', t_dif_t)

    3. 线程之间数据共享

    from threading import Thread
    
    num = 100
    def func():
        global num
        num = 0
    
    if __name__ == '__main__':
        t = Thread(target=func)
        t.start()
        print(num)
        t.join()
        print('主线程结束')
    View Code 线程间数据共享
    import time
    import random
    from threading import Thread
    
    n = 100
    def func():
        global n
        x = n
        x = x - 1
        time.sleep(random.random())
        n = x
    
    if __name__ == '__main__':
    
        for i in range(30):
            t_lst = []
            for i in range(10):
                t = Thread(target=func)
                t.start()
                t_lst.append(t)
            # [t.join() for t in t_lst]
            print(n)
    View Code 数据共享, 不安全
    import time
    from threading import Thread, Lock
    
    num = 100
    def func(t_lock):
        global num
        t_lock.acquire()
        mid = num
        mid = mid - 1
        time.sleep(0.0000001)
        num = mid
        t_lock.release()
    
    if __name__ == '__main__':
        t_lock = Lock()
        t_lst = []
        for i in range(10):
            t = Thread(target=func, args=(t_lock,))
            t.start()
            t_lst.append(t)
        [t.join() for t in t_lst]
    
        print('主线程>>>', num)
    View Code 共享数据加锁保障安全

    4. 锁(同步锁/互斥锁) 

      1. GIL (Global Interpreter Lock) 全局解释锁

      2. Lock  同步锁/互斥锁

      3. RLock  递归锁

      保证数据安全, 但是牺牲了效率, 同步执行锁内代码

      死锁现象: 当我们使用锁嵌套锁时, 多个线程异步执行的时候会出现线程之间相互争夺对方未释放的锁, 相互等待.   (互相抢到了对方需要的锁, 导致双方相互等待, 程序没法进行)

    import time
    from threading import Thread, Lock
    
    class MyThread(Thread):
    
        def __init__(self, lockA, lockB):
            super().__init__()
            self.lockA = lockA
            self.lockB = lockB
    
        def run(self):
            self.f1()
            self.f2()
    
        def f1(self):
            self.lockA.acquire()
            print('我拿了A锁')
            self.lockB.acquire()
            print('我拿了B锁')
            print('我是f1')
            self.lockB.release()
            self.lockA.release()
    
        def f2(self):
            self.lockB.acquire()
            time.sleep(1)
            print('拿到了B锁')
            self.lockA.acquire()
            print('拿到了A锁')
            print('我是f2')
            self.lockA.release()
            self.lockB.release()
    
    if __name__ == '__main__':
        lockA = Lock()
        lockB = Lock()
        t1 = MyThread(lockA, lockB)
        t1.start()
    
        t2 = MyThread(lockA, lockB)
        t2.start()
    
        print('我是主线程')
    View Code 死锁现象

       

      解决死锁: 递归锁 RLock   可以多次acquire, 通过一个计数器来记录被锁了多少次, 只有计数器为0的时候, 大家才能继续抢锁.

    import time
    from threading import Thread, Lock, RLock
    
    
    class MyThread(Thread):
    
        def __init__(self, lockA, lockB):
            super().__init__()
            self.lockA = lockA
            self.lockB = lockB
    
        def run(self):
            self.f1()
            self.f2()
    
        def f1(self):
            self.lockA.acquire()
            print('我拿了A锁')
            self.lockB.acquire()
            print('我拿了B锁')
            print('我是f1')
            self.lockB.release()
            self.lockA.release()
    
        def f2(self):
            self.lockB.acquire()
            time.sleep(1)
            print('拿到了B锁')
            self.lockA.acquire()
            print('拿到了A锁')
            print('我是f2')
            self.lockA.release()
            self.lockB.release()
    
    
    if __name__ == '__main__':
        lockA = lockB = RLock()
        t1 = MyThread(lockA, lockB)
        t1.start()
    
        t2 = MyThread(lockA, lockB)
        t2.start()
    
        print('我是主线程')
    View Code 递归锁, 解决死锁

     经典问题: 科学家吃面

    import time
    from threading import Thread,Lock, RLock
    
    def eat1(name, lockA, lockB):
        lockA.acquire()
        print('%s抢到了叉子' % name)
        lockB.acquire()
        print('%s抢到了面条' % name)
        print('%s开始吃面啦~~' % name)
        lockB.release()
        lockA.release()
    
    
    def eat2(name, lockA, lockB):
        lockB.acquire()
        print('%s抢到了面条' % name)
        time.sleep(1)
        lockA.acquire()
        print('%s抢到了叉子' % name)
        print('%s开始吃面啦~~~' % name)
        lockA.release()
        lockB.release()
    
    if __name__ == '__main__':
        lockA = lockB = RLock()
        # lockA = Lock()
        # lockB = Lock()
        for name in ['alex', 'wu sir', 'boss king', 'taibai']:
            t1 = Thread(target=eat1, args=(name, lockA, lockB))
            t1.start()
            t2 = Thread(target=eat2, args=(name, lockA, lockB))
            t2.start()
    View Code死锁和递归锁解决死锁

           

    5. 守护线程 

      主进程代码结束程序并没有结束,并且主进程还存在,进程等待其他的子进程执行结束以后,为子进程收尸,注意一个问题:主进程的代码运行结束守护进程跟着结束,

    守护线程:

      主线程等待所有非守护线程的结束才结束,主线程的代码运行结束,还要等待非守护线程的执行完毕.这个过程中守护线程还存在

    import time
    from multiprocessing import Process
    from threading import Thread
    
    def func(n):
        time.sleep(5)
        print(n)
    
    if __name__ == '__main__':
        # 主线程等待的是子线程的任务全部执行完毕
        t = Thread(target=func, args=('我是子线程',))
        t.start()
        # 主进程等待的是给子进程收尸, 回收资源,各种信息
        # p = Process(target=func, args=('我是子进程',))
        # p.start()
        print('主线程结束')
    View Code 主线程等待子线程的原因
    import time
    from multiprocessing import Process
    from threading import Thread
    
    def func1(n):
        time.sleep(5)
        print(n)
    
    def func2(n):
        time.sleep(2)
        print(n)
    
    if __name__ == '__main__':
        # p1 = Process(target=func1, args=('我是1号',))
        # p1.daemon = True
        # p1.start()
        # p2 = Process(target=func2, args=('我是2号',))
        # p2.start()
        t1 = Thread(target=func1, args=('我是1号',))
        # t1.daemon = True
        t1.start()
        t2 = Thread(target=func2, args=('我是2号',))
        t2.daemon = True  # 等待所有非守护线程结束
        t2.start()
    
        print('主线程结束')  # 守护进程在主进程运行代码结束时跟着结束, 不会跟着其他子进程执行
    View Code 守护线程与守护进程差别

      

    6. 信号量

      控制同时能够进入锁内去执行代码的线程数量(进程数量), 维护了一个计数器, 刚开始创建信号量的时候, 假如设置的是4个房间, 进入一次acquire就减1, 出来一个就+1, 如果计数器为0, name其他的任务等待, 这样其他的任务和正在执行的任务是一个同步的状态, 而进入acquire里面去执行的那4个任务是异步执行的.

    # 和进程中信号量的按摩房一个道理, 相当于有多把锁
    import time
    from threading import Thread, Semaphore
    
    def func1(s):
        s.acquire()
        time.sleep(1)
        print('你好啊')
        s.release()
    
    if __name__ == '__main__':
        s = Semaphore(4)
        for i in range(10):
            t = Thread(target=func1, args=(s,))
            t.start()

    超哥博客--Python之线程

  • 相关阅读:
    微信小程序 单选按钮 最佳
    微信小程序 单选按钮的实现
    微信小程序 单选框实现
    Java Code To Create Pyramid and Pattern
    Java language
    npm Err! Unexpected end of JSON input while parsing near
    Node.js Express FrameWork Tutorial
    Higher-Order Function Examples
    Create First HTTP Web Server in Node.js: Complete Tutorial
    Node.js NPM Tutorial: Create, Publish, Extend & Manage
  • 原文地址:https://www.cnblogs.com/surasun/p/9855334.html
Copyright © 2011-2022 走看看