zoukankan      html  css  js  c++  java
  • python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁

    ps:python解释器有很多种,最常见的就是C python解释器

    GIL全局解释器锁:
        GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全

        用来阻止同一个进程下的多个线程的同时执行(同一个进程内多个线程无法实现并行但是可以实现并发)

        GIL的存在是因为C python解释器的内存管理不是线程安全的

        垃圾回收机制:

            1、引用计数

            2、标记清除

            3、分代回收

        研究python 的多线程是否有用的话需要分情况讨论:

            同时执行四个任务  计算密集型:10s

    # 计算密集型
    from multiprocessing import Process
    from threading import Thread
    #mport os,time
    def work():
        res=0
        for i in range(100000000):
            res*=i
    
    
    if __name__ == '__main__':
        l=[]
        print(os.cpu_count())  # 本机为6核
        start=time.time()
        for i in range(6):
            # p=Process(target=work) #耗时  4.732933044433594
            p=Thread(target=work) #耗时 22.83087730407715
            l.append(p)
            p.start()
        for p in l:
            p.join()
        stop=time.time()
        print('run time is %s' %(stop-start))

            单核情况下:

                开线程更节省资源

            多核情况下:

                开进程:10s

                开线程:40s

            同时执行四个IO密集型任务

    # IO密集型
    from multiprocessing import Process
    from threading import Thread
    import threading
    import os,time
    def work():
        time.sleep(2)
    
    
    if __name__ == '__main__':
        l=[]
        print(os.cpu_count()) #本机为6核
        start=time.time()
        for i in range(4000):
            p=Process(target=work) #耗时9.001083612442017s多,大部分时间耗费在创建进程上
            # p=Thread(target=work) #耗时2.051966667175293s多
            l.append(p)
            p.start()
        for p in l:
            p.join()
        stop=time.time()
        print('run time is %s' %(stop-start))

            单核:开线程更省资源

            多核:开线程更省资源

        

    Event事件:

        

    from threading import Event,Thread
    import time
    
    # 先生成一个event对象
    e = Event()
    
    
    def light():
        print('红灯正亮着')
        time.sleep(3)
        e.set()  # 发信号
        print('绿灯亮了')
    
    def car(name):
        print('%s正在等红灯'%name)
        e.wait()  # 等待信号
        print('%s加油门飙车了'%name)
    
    t = Thread(target=light)
    t.start()
    
    for i in range(10):
        t = Thread(target=car,args=('伞兵%s'%i,))
        t.start()

    信号量:在不同的领域中,对应不同的知识点

        互斥锁:一个厕所(一个坑)
        信号量:公共厕所(多个坑位)

    from threading import Semaphore,Thread
    import time
    import random
    
    
    sm = Semaphore(5)  # 造了一个含有五个的坑位的公共厕所
    
    def task(name):
        sm.acquire()
        print('%s占了一个坑位'%name)
        time.sleep(random.randint(1,3))
        sm.release()
    
    for i in range(40):
        t = Thread(target=task,args=(i,))
        t.start()

      

    死锁:

        RLock可以被第一个抢到锁的人连续的acquire和release

        每acquire一次锁身上的计数就加1

        每release一次锁身上的计数就减1

        只要是锁的计数不为0 其他人都不能抢

    class MyThread(Thread):
        def run(self):  # 创建线程自动触发run方法 run方法内调用func1 func2相当于也是自动触发
            self.func1()
            self.func2()
    
        def func1(self):
            mutexA.acquire()
            print('%s抢到了A锁'%self.name)  # self.name等价于current_thread().name
            mutexB.acquire()
            print('%s抢到了B锁'%self.name)
            mutexB.release()
            print('%s释放了B锁'%self.name)
            mutexA.release()
            print('%s释放了A锁'%self.name)
    
        def func2(self):
            mutexB.acquire()
            print('%s抢到了B锁'%self.name)
            time.sleep(1)
            mutexA.acquire()
            print('%s抢到了A锁' % self.name)
            mutexA.release()
            print('%s释放了A锁' % self.name)
            mutexB.release()
            print('%s释放了B锁' % self.name)
    
    for i in range(10):
        t = MyThread()
        t.start()

    递归锁:

    import threading
     
     
    class MyThread(threading.Thread):
     
        def run(self):
            global n1, n2
            lock.acquire()   # 加锁
            n1 += 1
            print(self.name + ' set n1 to ' + str(n1))
            lock.acquire()   # 再次加锁
            n2 += n1
            print(self.name + ' set n2 to ' + str(n2))
            lock.release()
            lock.release()
     
    n1, n2 = 0, 0
    lock = threading.RLock()
     
    if __name__ == '__main__':
        thread_list = []
        for i in range(5):
            t = MyThread()
            t.start()
            thread_list.append(t)
        for t in thread_list:
            t.join()
        print('final num:%d ,%d' % (n1, n2))
  • 相关阅读:
    Docker配置mysql
    Docker中部署Redis
    Linux上docker的安装
    tomcat启动报错:To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
    导出excel表格不能用ajax
    linux安装jdk
    第三次实验报告:使用Packet Tracer分析TCP连接建立过程
    第二次实验报告:使用Packet Tracer分析应用层协议
    第一次实验报告:使用Packet Tracer分析HTTP数据包
    PYTHON——多线程:队列Queue数据结构
  • 原文地址:https://www.cnblogs.com/tulintao/p/11354459.html
Copyright © 2011-2022 走看看