• 信号量/死锁与递归锁/时间与Event/定时器和线程queue/GIL全局解释器锁


    昨日复习:

    1.线程:

    (1)同一进程下的多个线程共享该进程的内存资源

    (2)开启线程的开销远远小于开启进程

    2.线程,进程,互斥锁的概念

    https://mp.weixin.qq.com/s?__biz=MzIwNTc4NTEwOQ==&mid=2247484323&idx=1&sn=ea7e50be369f9992c6305555554a1252&chksm=972ad2d9a05d5bcfa9216d59cb063970f5bb52f262e657de9978db0250a90e84a9f49a8f0f7a&mpshare=1&scene=23&srcid=0106KZS0oSBKryf95uvWo3HU#rd

     3.守护进程和守护线程

    守护线程:是守护的主线程的生命的周期,就是它所有的子线运行完才结束

    守护进程:守护的是主进程的代码运行

    4.生产者和消费者模型:

        模型就是编程的一种套路,来解决一种问题,你的任务有一个非常明显的特点,有一堆任务在造数据,一堆在取数据,两者通过解耦合的方式通过队列来提升效率互相不用等,这样造数据和取数据可以提升效率一直在造和取 ,类似快递柜

    今日内容:

    一:信号量

    本质也是种一个锁,有多个锁可以加;类似于公共厕所

    from threading import Thread,Semaphore,current_thread
    import time,random
    
    def func():
        sm.acquire()                    #开启
        print('%s is wcing'%current_thread().getName())
        time.sleep(random.randint(1,5))
        sm.release()                     #释放
    
    if __name__ == '__main__':
        sm=Semaphore(5)                 #类似于5把钥匙 
        for i in range(23):
            t=Thread(target=func)
            t.start()
    
    结果是:
    Thread-1 is wcing
    Thread-2 is wcing
    Thread-3 is wcing
    Thread-4 is wcing
    Thread-5 is wcing
    Thread-6 is wcing
    Thread-7 is wcing
    Thread-8 is wcing
    Thread-9 is wcing
    Thread-10 is wcing
    Thread-11 is wcing
    Thread-12 is wcing
    Thread-13 is wcing
    Thread-14 is wcing
    Thread-15 is wcingThread-16 is wcing
    
    Thread-17 is wcing
    Thread-18 is wcingThread-19 is wcing
    Thread-20 is wcing
    
    Thread-21 is wcing
    Thread-22 is wcing
    Thread-23 is wcing

    二:死锁与递归锁

    锁套锁用递归锁,除非全部解锁其他才可以抢,也就是它的上面计数为0

    死锁:
    
    from threading import Thread,Lock
    import time
    
    mutexA=Lock()
    mutexB=Lock()
    
    class Mythread(Thread):
        def __init__(self,name):
            super().__init__()
            self.name=name
        def run(self) -> None:
            self.f1()
            self.f2()
        def f1(self):
            mutexA.acquire()
            print('%s抢到了A锁'%self.name)
    
            mutexB.acquire()
            print('%s抢到了B锁'%self.name)
            mutexB.release()
            mutexA.release()
    
        def f2(self):
            mutexB.acquire()
            print('%s抢到了B锁'%self.name)
            time.sleep(0.1)
            mutexA.acquire()
            print('%s抢到了A锁'%self.name)
            mutexA.release()
            mutexB.release()
    
    if __name__ == '__main__':
        t1=Mythread('线程1')
        t2=Mythread('线程2')
        t3=Mythread('线程3')
        t4=Mythread('线程4')
        t1.start()
        t2.start()
        t3.start()
        t4.start()
        print('主线程')
    
    结果:
    线程1抢到了A锁
    线程1抢到了B锁
    线程1抢到了B锁
    线程2抢到了A锁
    主线程
    
    程序停止在原地

    解决办法-----递归锁

    from threading import Thread,RLock,Lock
    import time
    
    mutexA = mutexB = RLock()           #Rlock类似于一个人使用一个门中的多个厕所:一个人拿到钥匙后mutex.acquire,就会在他身上标记一个数字,直到他身上的数字为0时下一个才可使用 
    
    class Mythread(Thread):
        def __init__(self,name):
            super().__init__()
            self.name = name
    
        def run(self) -> None:
            self.f1()
            self.f2()
    
        def f1(self):
            mutexA.acquire()
            print("%s 抢到了A锁" %self.name)
    
            mutexB.acquire()
            print("%s 抢到了B锁" %self.name)
            mutexB.release()
    
            mutexA.release()
    
    
        def f2(self):
            mutexB.acquire()
            print("%s 抢到了B锁" % self.name)
            time.sleep(0.1)
    
            mutexA.acquire()
            print("%s 抢到了A锁" % self.name)
            mutexA.release()
    
            mutexB.release()
    
    if __name__ == '__main__':
        t1 = Mythread("线程1")
        t2 = Mythread("线程2")
        t3 = Mythread("线程3")
        t4 = Mythread("线程4")
    
        t1.start()
        t2.start()
        t3.start()
        t4.start()
        print("主线程")
    结果是:
    线程1 抢到了A锁
    线程1 抢到了B锁
    线程1 抢到了B锁
    主线程
    线程1 抢到了A锁
    线程2 抢到了A锁
    线程2 抢到了B锁
    线程2 抢到了B锁
    线程2 抢到了A锁
    线程4 抢到了A锁
    线程4 抢到了B锁
    线程4 抢到了B锁
    线程4 抢到了A锁
    线程3 抢到了A锁
    线程3 抢到了B锁
    线程3 抢到了B锁
    线程3 抢到了A锁

    三:时间与Event

    底层维护了一个全局变量的,默认的是False

    一个线程运行完再运行另外一个程序:

    from threading import Event,Thread,current_thread
    import time
    e=Event()   #全局的变量,默认是False
    
    def f1():
        print('%s 运行'%current_thread().name)
        time.sleep(3)
        e.set()  #把全局变量改为True
        #e.clear()把全局变量改为False    e.is_set() 是否是set过  就是是否是True
    
    def f2():
        e.wait()
        print('%s 运行'%current_thread().name)
    
    if __name__ == '__main__':
        t1=Thread(target=f1)
        t2=Thread(target=f2)
        t1.start()
        t2.start()
    结果是:
    Thread-1 运行
    Thread-2 运行

    例子2~红绿灯模拟

    from threading import Thread,Event,current_thread
    import time,random
    
    e=Event()
    
    def task1():
        while True:
            e.clear()
            print('红灯亮')
            time.sleep(2)
    
            e.set()
            print('绿灯亮')
            time.sleep(3)
    
    def task2():
        while True:
            if e.is_set():
                print('%s 走你'%current_thread().name)
                break
            else:
                print('%s等灯'%current_thread().name)
                e.wait()
    
    if __name__ == '__main__':
       Thread(target
    =task1).start() while True: time.sleep(random.randint(1,3)) Thread(target=task2).start() 结果是:

    红灯亮
    Thread-2等灯
    绿灯亮
    Thread-2 走你
    Thread-3 走你
    红灯亮
    Thread-4等灯
    绿灯亮Thread-4 走你

    四:定时器和线程queue

    定时器

    from threading import Timer
    def hello(n):
        print('hello world',n)
    t=Timer(3,hello,args=(1111,))   时间,函数hello,还可以传参
    t.start()
    结果是:
    hello world 1111

    线程queue

    import  queue
    #队列(先进先出)
    q=queue.Queue(3)
    q.put(111)
    q.put(222)
    q.put(333)
    print(q.get())
    print(q.get())
    print(q.get())
    #结果:111,2,2,333
    
    #堆栈(先进后出)
    q=queue.LifoQueue(3)
    q.put(111)
    q.put(222)
    q.put(333)
    print(q.get())
    print(q.get())
    print(q.get())
    #结果是:333,222,111
    
    #优先级队列
    q=queue.PriorityQueue(3)
    q.put((1,111))   #里面放一个小元组,第一个是取出的顺序
    q.put((5,222))
    q.put((-1,333))
    print(q.get())
    print(q.get())
    print(q.get())
    #结果是:
    (-1, 333)
    (1, 111)
    (5, 222)

    五:GIL全局解释器锁******

    cpython解释器同一进程下的多个线程,同一时刻只能有一个线程执行,不能同时进行,CPU多核优势用不上

    六:协程

    1.单个线程下应用程序自己实现并发的概念,操作系统的并发只是针对进程而言‘如果遇到io行为会被操作系统认为’整体是io而拿走cup而停在原地,也就是用不上多核的优势的。

    2.要实现多个任务并发的概念:

      1.开4个进程,每个进程1个线程

      2.开2个进程,每个进程开2个线程

      3.开一个进程,应用程序控制切数据,在1个线程下快速切

  • 相关阅读:
    让Vim查找字符忽略大小写
    How to Add a User to Sudoers on Ubuntu
    Docker 批量删除images
    解决 Laradock 安装时候出现 Can't open /home/laradock/.nvm/nvm.sh 的问题
    Add User To Docker Group In Ubuntu Linux
    Parted分区和创建逻辑卷LVM
    How To List Users and Groups on Linux
    How to Install Node.js and NPM on Mac OS
    linux中的alias命令详解
    Hadoop数据类型
  • 原文地址:https://www.cnblogs.com/dayday-up-a/p/14311798.html
Copyright © 2020-2023  润新知