线程知识点(锁,信号量,队列,条件)

 

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())

 

posted @ 2018-09-25 19:57  雷文轩  阅读(293)  评论(0编辑  收藏  举报