• GIL全局解释器 GIL与普通的互斥锁 死锁 信号量 event 线程


    GIL全局解释器 

    In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple
    native threads from executing Python bytecodes at once. This lock is necessary mainly
    because CPython’s memory management is not thread-safe.


    python解释器有很多种 最常见的是CPython解释器
    GIL自己的本事也是一把互斥锁,他是将并发变成串行,这样做会牺牲效率保证数据的安全
    用来组织 同一个进程下的多个线程的同时进行(同一个进程内多个线程是无法并行的,但是可以实现并发)
    python的多线程没法利用多核优势 是不是就没有用了

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

    垃圾回收机制
    1 引用计数
    2 标机回收
    2 分代回收

    python的多线程是否有用分情况讨论 在同样都是四个任务的情况下
    计算密集型的 用时10s
    单核情况下
    开线程更省资源
    多核情况下
    开进程 用时10s
    开线程 用时40s

    IO密集型的
    单核情况下
    开线程更节省资源
    多核情况下
    开线程更节省资源

     

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



    # 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(400):
    # p=Process(target=work) #耗时16.240999937057495s多,大部分时间耗费在创建进程上
    p=Thread(target=work) #耗时2.0390000343322754s多
    l.append(p)
    p.start()
    for p in l:
    p.join()
    stop=time.time()
    print('run time is %s' %(stop-start))


    # 总结
    # python中的多线程 需要看情况而定 而且用处是肯定有的 后期要多进程+多线程配合使用

    GIL与普通的互斥锁   

    from threading import Thread
    import time
    
    n = 100
    
    
    def task():
        global n
        tmp = n
        time.sleep(1)
        n = tmp -1
    
    t_list = []
    for i in range(100):
        t = Thread(target=task)
        t.start()
        t_list.append(t)
    
    for t in t_list:
        t.join()
    
    print(n)

    死锁 

    自己千万不要轻易的处理锁的问题 


    Rlock可以被第一个抢到锁的人连续的acquire和release
    每acquire一次锁身上的计数加1
    每release一次锁身上的计数减1
    只要锁的计数不为0 其他人都不能抢
    from threading import Thread,Lock,current_thread,RLock
    import time
    # mutexA = Lock()
    # mutexB = Lock()
    mutexA = mutexB = RLock()  # A B现在是同一把锁
    
    
    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()

    信号量

    信号量可能是在不同的领域中 对应不同的知识点

    互斥锁:家用厕所(就是说只有一个坑)
    信号量:公共厕所(有多个坑使用)

    信号量就是多个人在做同一件事情的时 所需要的公共位置

       

    from threading import Thread,Semaphore
    import time
    import random
    
    wc = Semaphore(5)   #参数相当是有多少位置
    
    def task(name):
        wc.acquire()
        print('%s 占了一个坑'%name)
        time.sleep(random.randint(1,3))
        wc.release()
    
    for i in range(20):
        t = Thread(target=task,args=(i,))
        t.start()

    event   

    from threading import Event,Thread
    import time
    
    e = Event()   # 生生成一个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()

    线程

    同一个进程下的多个线程本来就是数据共享  为什么还要用队列

    队列是 管道+锁 使用队列的话 就不需要自己来操作锁

    锁操作的不好的话 会造成死锁现象
    import queue
    q = queue.Queue()
    q.put('hahha')
    print(q.get())
    # LifoQueue   后进线出
    import queue
    q = queue.LifoQueue()
    q.put(1)
    q.put(2)
    q.put(3)
    print(q.get())
    # PriorityQueue     数字的优先级     数字越小   优先级越高
    
    import queue
    q = queue.PriorityQueue()
    
    q.put((10,'haha'))
    q.put((100,'hehehe'))
    q.put((-50,'xxxx'))
    q.put((-10,'yyyy'))
    
    print(q.get())  # (-50, 'xxxx')
    print(q.get())  # (-10, 'yyyy')
    print(q.get())  # (10, 'haha')
    print(q.get())  # (100, 'hehehe')
  • 相关阅读:
    TCP源码—连接建立
    TCP系列02—连接管理—1、三次握手与四次挥手
    TCP系列01—概述及协议头格式
    ubuntu软件管理apt与dpkg
    318. Maximum Product of Word Lengths
    317. Shortest Distance from All Buildings
    316. Remove Duplicate Letters
    315. Count of Smaller Numbers After Self
    314. Binary Tree Vertical Order Traversal
    313. Super Ugly Number
  • 原文地址:https://www.cnblogs.com/xuzhaolong/p/11352378.html
Copyright © 2020-2023  润新知