zoukankan      html  css  js  c++  java
  • 4,GIL全局解释器锁,event事件,信号量

    今日内容
    1,GIL全局解释器锁
    2,死锁
    3,信号量
    4,event事件
    5,队列
    一:GIL全局解释器锁
    什么是GIL 全局解释器锁:
    它的本质也是一把互斥锁,是在CPython解释器锁,将并发变为串行的,
    牺牲效率,保证数据安全性!
    作用:用来阻止同一个进程下的多个线程的同时执行
    (同一个进程内多个线程无法实现并行但是可以实现并发)
    GIL的存在是因为CPython解释器的内存管理不是线程安全的
    研究python的多线程是否有用需要分情况讨论
    四个任务 计算密集型的 10s
    单核情况下
    开线程更省资源
    多核情况下
    开进程 10s
    开线程 40s

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






    2 死锁:

    from threading import Thread,Lock,current_thread,RLock
    import time

    # RLock 递归锁
    # Rlock可以被第一个抢到锁的人连续的acquire和release
    #每acquire一次锁身上的计数加1
    #每release一次锁身上的计数减1
    #只要锁的计数不为0 其他人都不能抢


    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()
    3,信号量 (Semaphore)
    # 信号量可能在不同的领域中 对应不同的知识点

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

    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()
    4,event事件 一个子进程等待另一个子进程接受再走,或者一个子线程等待另一个子线程结束再走
    即 子等子时,就用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()

    5,队列(多线程优先用队列,而不是加锁)
    同一个进程下的多个线程本来就是数据共享 为什么还要用队列
    因为队列是管道+锁 使用队列你就不需要自己手动操作锁的问题
    因为锁操作的不好极容易产生死锁现象
    import queue

    q = queue.Queue() # 普通队列,产生一个队列对象
    q.put('hahha')
    print(q.get())


    q = queue.LifoQueue() #后进先出队列,==》堆栈
    q.put(1)
    q.put(2)
    q.put(3)
    print(q.get())


    q = queue.PriorityQueue() #优先级队列,支持你给你放的数据设置优先级,
    取的时候,数字越小 优先级越高***********
    q.put((10,'haha'))
    q.put((100,'hehehe'))
    q.put((0,'xxxx'))
    q.put((-10,'yyyy'))
    print(q.get())
  • 相关阅读:
    Kafka常用操作备忘
    Spark执行流程(转)
    Spark性能优化总结
    Kafka学习笔记
    vue-简单例子初始化
    解析字符串模板函数
    js的apply 和 call区别
    水平垂直居中
    IE8 div旋转 Matrix,模拟轮播前后翻页按钮
    jsp 自定义标签-SimpleTagSupport 使用笔记
  • 原文地址:https://www.cnblogs.com/Fzhiyuan/p/11353667.html
Copyright © 2011-2022 走看看