zoukankan      html  css  js  c++  java
  • 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')
  • 相关阅读:
    PHP查找服务器某个目录下的文件
    CentOS添加用户,管理员权限
    centos图形化桌面安装过程
    正则表达式匹配查询
    Windows远程桌面多用户登录的问题
    VM虚拟机Android安装图形界面
    Ubuntu 根目录作用
    win7个性化不能换界面:此页面上的一个或多个设置已被系统管理员禁用,关机里的切换用户和锁定为灰色
    springboot 使用 jedis 连接 Redis 数据库
    JAVA 中 Map 与实体类相互转换的简单方法
  • 原文地址:https://www.cnblogs.com/xuzhaolong/p/11352378.html
Copyright © 2011-2022 走看看