zoukankan      html  css  js  c++  java
  • 线程知识点(锁,信号量,队列,条件)

    1线程锁

    1.1GIL

    1.2线程之间的数据安全问题

    例如:多个线程对同一块数据进行操作;
            比如赋值运算, 一个线程那到数据还没有返回数据结果时间片轮转,引起数据的不安全;
        pop, append 操作是安全的,
        队列也是安全的
    

    具体操作

    `此处输入代码
    from threading import Thread, Lock`
    lock.acquire()
    '''
        对数据的操作
    '''
    lock.release()
    

    1.3递归锁和死锁现象

    死锁

     是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁
    
    死锁现象
        两把锁
        异步的                                                                  
        操作的时候 抢到一把锁之后还要再去抢第二把锁
        一个线程抢到一把锁
        另一个线程抢到了另一把锁
    

    解决办法

    解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:
    

    示例代码

    import time                                  
    def fun(lock):                               
        lock.acquire()                           
        print('我还活着')                            
        lock.release()                           
        time.sleep(1)                            
        lock.acquire()                           
        print('你还没死')                            
        lock.release()                           
    def func(lock):                              
        lock.acquire()                           
        lock.acquire()                           
        print('没死')                              
        lock.release()                           
        lock.release()                           
    
    
    if __name__ == '__main__':                   
        lock = Lock()                            
        # for i in range(10):                    
        t1 = Thread(target=fun, args=(lock,))    
        t1.start()                               
        t2 = Thread(target=func, args=(lock,))   
        t2.start()      
    

    递归锁

    在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生生死锁
    

    具体代码

    from threading import Thread, RLock         
    fork_lock = noodle_lock = RLock()# 一把锁      
    def fun1(*args):                            
        noodle_lock.acquire()                   
        #具体操作                                   
        fork_lock.acquire()                     
        # 具体操作                                  
        fork_lock.release()                     
        noodle_lock.release()  #只有当锁释放后才能执行其他操作
    

    递归锁可以解决互斥锁的死锁问题

    # 互斥锁
     ¦   # 两把锁
     ¦   # 多个线程抢
     # 递归锁
     ¦   # 一把锁
     ¦   # 多个线程抢
    

    递归锁能够快速的解决死锁问题

      # 递归锁好不好?
      不好, 出现死锁,肯定是程序的逻辑有问题, 在快速解决死锁的情况下, 修改程序的逻辑。
     递归锁
     迅速恢复服务 递归锁替换互斥锁
         在接下来的时间中慢慢把递归锁替换成互斥锁
         能够完善代码的逻辑
         提高代码的效率
    多个线程之间,用完一个资源再用另外一个资源
    先释放一个资源,再去获取一个资源的锁
    

    信号量

    与进程的的信号量用法一样
    

    事件Event

    wait() 等待 事件内的信号编程True
    set()  把信号变成True
    clear  把信号变成False
    is_set 查看信号状态是否为True
    

    示例代码

    from threading import
    import time          
    
    def fun1(e):         
        e.wait()   #在set没有调用之前下面的语句不执行 
        print('你好呀,我来了') 
    def fun2(e):         
        time.sleep(5)    
        e.set()          
    
    if __name__ == '__mai
        e = Event()      
        t1 = Thread(targe
        t1.start()       
        t2 = Thread(targe
        t2.start()       
    

    条件 Condition

    Python提供的Condition对象提供了对复杂线程同步问题的支持。Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。不断的重复这一过程,从而解决复杂的同步问题
    from threading import Condition, Thread                                         
    def fun(con, name):                                                              
        print('欢迎光临')                                                           
        con.acquire()                                                                
        con.wait()     #使用前后都需要加锁                                           
        print('%s go to school'%name)                                                
        con.release()                                                           
    if __name__ == '__main__':                                                    
        con = Condition()                                                                  
        for i in range(10):                                                                
            t = Thread(target=fun, args=(con, i))                                          
            t.start()                                                                      
        con.acquire()                                                                      
        # con.notify(4)   #使用前后都需要加锁  每次默认一个,参数代表通过的次数                                     
        # con.notify_all()                                                                 
        con.notifyAll()                                                                    
        con.release()       
    

    定时器 Timer

    定时器,指定n秒后执行某个操作

    from threading import Thread, Timer                       
    def func():                                               
        print('Timer: going to ')                             
    if __name__ == '__main__':                                
        t = Timer(5, func)                                    
        t.start()                                   
    

    线程队列 queue队列

    跟队列进程队列一样的用法

    q = queue.Queue()         
    q.put(1)                  
    q.put(2)                  
    q.put(3)                  
    #先进先出原则                   
    print(q.get())    #1      
    print(q.get())    #2      
    print(q.get())    #3      
    

    线程队列 LifoQueue

    和栈类似先进后出

    from queue import LifoQueue
    q = LifoQueue()
    q.put(1)
    q.put(2)
    q.put(3)
    print(q.get()) #3
    print(q.get()) #2
    print(q.get()) #1
    

    PriorityQueue

    存储数据时可设置优先级的队列

    from queue import PriorityQueue
    q = PriorityQueue()
    q.put((3,'lei'))
    q.put((2,'wen'))
    q.put((1,'xuan'))
    print(q.get())
    print(q.get())
    print(q.get())
    
  • 相关阅读:
    LeetCode 79. 单词搜索
    LeetCode 1143. 最长公共子序列
    LeetCode 55. 跳跃游戏
    LeetCode 48. 旋转图像
    LeetCode 93. 复原 IP 地址
    LeetCode 456. 132模式
    LeetCode 341. 扁平化嵌套列表迭代器
    LeetCode 73. 矩阵置零
    LeetCode 47. 全排列 II
    LeetCode 46. 全排列
  • 原文地址:https://www.cnblogs.com/leiwenxuan/p/9703062.html
Copyright © 2011-2022 走看看