zoukankan      html  css  js  c++  java
  • 锁、threading.local、线程池

    一、锁

      Lock(1次放1个)

        什么时候用到锁:

          线程安全,多线程操作时,内部会让所有线程排队处理。如:list、dict、queue

          线程不安全,

    import threading
    import time
    v = []
    lock = threading.Lock()        #实例化了一个对象******
    def func(arg):
        lock.acquire()    #加锁
        v.append(arg)
        time.sleep(0.5)
        m = v[-1]
        print(arg,m)
        lock.release()    #加锁就要有解锁对应
    for i in range(1,11):
        t = threading.Thread(target=func,args=(i,))
        t.start()

      RLock(1次放1个)

        与Lock用法一致,但是RLock可以锁多次(必须有响应的解锁次数),Lock只能锁一次

    import threading
    import time
    v = []
    lock = threading.RLock()
    def func(arg):
        lock.acquire()  #锁了两次
        lock.acquire()
        v.append(arg)
        time.sleep(0.1)
        m = v[-1]
        print(arg,m)
        lock.release()  #解锁两次
        lock.release()
    
    for i in range(1,11):
        t = threading.Thread(target=func,args=(i,))
        t.start()

      BoundedSemaphore(1次方固定个数个)

    import time
    import threading
    lock = threading.BoundedSemaphore(3)    #参数是多少就一次放过去多少个线程
    def func(arg):
        lock.acquire()
        print(arg)
        time.sleep(1)
        lock.release()
    for i in range(1,11):
        t = threading.Thread(target=func,args=(i,))
        t.start()

      Condition(1次放N个)

    import time
    import threading
    lock = threading.Condition()
    def func(arg):
        print("start")
        lock.acquire()
        lock.wait()    #****
        print(arg)
        time.sleep(1)
        lock.release()
    for i in range(1,11):
        t = threading.Thread(target=func,args=(i,))
        t.start()
    while 1:
        num = int(input(">>>>>"))    #输入多少本次就会放多少个线程
        lock.acquire()    #****
        lock.notify(num)
        lock.release()    #****
    #也可以通过函数逻辑判断的返回值
    def xx():
        print("来执行函数了")
        input(">>>>")
        return True
    def func(arg):
        print("线程来了")
        lock.wait_for(xx)
        print(arg)
        time.sleep(1)
    for i in range(1,11):
        t = threading.Thread(target=func,args=(i,))
        t.start()

      Event(1次放所有)

    import threading
    lock = threading.Event()
    def func(arg):
        print("线程来了")
        lock.wait()#加锁
        print(arg)
    for i in range(1,11):
        t = threading.Thread(target=func,args=(i,))
        t.start()
    input(">>>>")
    lock.set()  #解锁,如果后面不加锁上面的wait就失效了
    input(">>>>")
    lock.clear()    #再次上锁
    for i in range(1,11):
        t = threading.Thread(target=func,args=(i,))
        t.start()
    input(">>>>")
    lock.set()

      总结:

        线程安全,列表和字典线程安全

        为什么要加锁:

          非线程安全

          控制一段代码

    二、threading.local

      作用:

        内部自动为每个线程维护一个空间(字典),用于当前存取属于自己的值。保证线程之间的数据隔离

        {

          线程id:{......}

          线程id:{......}

          线程id:{......}

        }

    import time
    import threading
    v = threading.local()
    def func(arg):
        # 内部会为当前线程创建一个空间用于存储:phone=自己的值
        v.phone = arg
        time.sleep(1)
        print(v.phone,arg)  # 去当前线程自己空间取值
    for i in range(1,11):
        t = threading.Thread(target=func,args=(i,))
        t.start()
    import time
    import threading
    
    DATA_DICT = {}
    
    def func(arg):
        ident = threading.get_ident()
        DATA_DICT[ident] = arg
        time.sleep(1)
        print(DATA_DICT[ident],arg)
    
    for i in range(10):
        t =threading.Thread(target=func,args=(i,))
        t.start()
    threading.local原理
    import time
    import threading
    INFO = {}
    class Local(object):
        def __getattr__(self, item):
            ident = threading.get_ident()
            return INFO[ident][item]
        def __setattr__(self, key, value):
            ident = threading.get_ident()
            if ident in INFO:
                INFO[ident][key] = value
            else:
                INFO[ident] = {key:value}
    obj = Local()
    def func(arg):
        obj.phone = arg     #对象.xx="xxx" 调用了__setattr__方法
        time.sleep(1)
        print(obj.phone,arg)    #对象.xx 调用了__getattr__方法
    for i in range(1,11):
        t = threading.Thread(target=func,args=(i,))
        t.start()
    threading.local原理升级版

    三、线程池

    from concurrent.futures import ThreadPoolExecutor
    import time
    def func(a1,a2):
        time.sleep(1)
        print(a1,a2)
    #创建了一个线程池(最多5个线程)
    pool = ThreadPoolExecutor(5)
    for i in range(1,21):
    #去线程池中申请一个线程
        pool.submit(func,i,"a")

    四、生产者消费者模型

      三部件:

        生产者

          队列,先进先出

          栈,后进先出

        消费者

      生产者消费者模型解决了什么问题:不用一直等待的问题

    import time
    import threading
    import queue
    q = queue.Queue()#线程安全
    def producer(id):
        while 1:
            time.sleep(2)
            q.put("包子")
            print("厨师%s生产了一个包子"%id)
    for i in range(1,3):
        t = threading.Thread(target=producer,args=(i,))
        t.start()
    def consumer(id):
        while 1:
            time.sleep(1)
            q.get("包子")
            print("顾客%s吃了一个包子"%id)
    for i in range(1,4):
        t = threading.Thread(target=consumer,args=(i,))
        t.start()
    示例
  • 相关阅读:
    Oracle-创建PDB
    win10怎么看IP地址、怎么看主机名
    怎么读dll文件
    Windows的注册表是什么?
    DbHelperOra类的相关链接(没看)
    C#中//注释和///注释的区别
    有关C#的序列化
    【智能指针 | 01】std::shared_ptr的使用教程
    coreump
    d
  • 原文地址:https://www.cnblogs.com/qq849784670/p/9628841.html
Copyright © 2011-2022 走看看