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())
    
  • 相关阅读:
    最短路
    Codeforces Round #607 (Div. 2) C. Cut and Paste
    第三次训练赛
    训练赛
    day27-反射
    day26-网络编程
    tcp文件上传--多个客户端
    tcp图片上传
    tcp文件上传优化
    tcp文件上传
  • 原文地址:https://www.cnblogs.com/leiwenxuan/p/9703062.html
Copyright © 2011-2022 走看看