• 锁、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()
    示例
  • 相关阅读:
    LightOJ 1132 Summing up Powers(矩阵快速幂)
    hdu 3804 Query on a tree (树链剖分+线段树)
    LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)
    uva 12304 2D Geometry 110 in 1! (Geometry)
    LA 3263 That Nice Euler Circuit (2D Geometry)
    2013 SCAUCPC Summary
    poj 3321 Apple Tree (Binary Index Tree)
    uva 11796 Dog Distance (几何+模拟)
    uva 11178 Morley's Theorem (2D Geometry)
    动手动脑
  • 原文地址:https://www.cnblogs.com/qq849784670/p/9628841.html
Copyright © 2020-2023  润新知