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())
  • 相关阅读:
    bzoj 1017 魔兽地图DotR
    poj 1322 chocolate
    bzoj 1045 糖果传递
    poj 3067 japan
    timus 1109 Conference(二分图匹配)
    URAL 1205 By the Underground or by Foot?(SPFA)
    URAL 1242 Werewolf(DFS)
    timus 1033 Labyrinth(BFS)
    URAL 1208 Legendary Teams Contest(DFS)
    URAL 1930 Ivan's Car(BFS)
  • 原文地址:https://www.cnblogs.com/Fzhiyuan/p/11353667.html
Copyright © 2011-2022 走看看