[Python] Python 多线程 Envent 解决数据共享问题


vent对象实现了简单的线程通信机制,它提供了设置信号,清楚信号,等待等用于实现线程间的通信。

   1 设置信号

   使用Event的set()方法可以设置Event对象内部的信号标志为真。Event对象提供了isSet()方法来判断其内部信号标志的状态。当使用event对象的set()方法后,isSet()方法返回真

   2 清除信号

   使用Event对象的clear()方法可以清除Event对象内部的信号标志,即将其设为假,当使用Event的clear方法后,isSet()方法返回假

   3 等待

   Event对象wait的方法只有在内部信号为真的时候才会很快的执行并完成返回当Event对象的内部信号标志位假时,则wait方法一直等待到其为真时才返回。



本实例解决这样的需求:

A 线程会每隔一段时间更新一块内存区域, 如一个字典 dict.

B 线程会不断读 dict.

那么为了防止 B 线程读 dict 时 A 线程在做更新, 以及 A 线程在做更新时 B 线程在读, 需要使用 Event 来解决此问题。

A 线程在更新时, 首先检查 B 线程是否在读, 若在读, A 线程等待. 
B 线程每次读的时候会首先检查 A 线程是否在更新, 在更新时 B 不读, 略过, 没有更新时, B 线程读 dict, 读之前设置一个信号量, 读完通知 A 线程更新。

A 线程更新时, 可以设置两个内存区域, 
dict_new 保存新值
dict 保存旧值

在更新时只需要做指针赋值即可, 这样会很快.



import sys
import threading
import time

event1 = threading.Event()
event2 = threading.Event()

event1.set() # 初始内部标志为真.
event2.set()

class RelTweet(threading.Thread): #The timer class is derived from the class threading.Thread
    def __init__(self, num):
        threading.Thread.__init__(self)
        
        self.thread_num = num
        self.thread_stop = False
        
        self.dataIsUsed = 0
        self.dataUpdate = 0 # 0-not update, 1-updated, 2-updating, condition variable
        self.dict = {}
        
        # init dict
        self.dataUpdate = 1
        self.dict["qq"] = 100
 
    def run(self): #Overwrite run() method, put what you want the thread do here
        print '[thread] Thread  %d running.' %(self.thread_num)
        i = 0
        while not self.thread_stop:
            
            time.sleep(3) # updtae interval is 3 seconds.
            
            if self.thread_stop == False: # 停止当前线程 #
                break
                   
             if not event2.isSet(): # 若信号 event2 为假, 一直等待.
                event2.wait() # 当前线程等待, 当 event2 被设置为真 (调用 set 方法时). 当前线程被唤醒. 继续执行
                print "update thread wait"
                
            if self.thread_stop == False: # 停止当前线程 #
                break
                
            print "[thread] updating dict"
            
             event1.clear()
            
            i += 1
            self.dict["qq"] = i
            time.sleep(3) # update used 3 seconds.
            
             event1.set()
            
            print "[thread] updating dict finish"
            
            
    def stop(self):
        self.thread_stop = True
       
 
def test():
    thread1 = RelTweet(1)
    
    print "[main] thread start"
    
    thread1.start()
    
    print "[main] running"
    
    loop = 1000
    while True:
        try:
            if loop <= 0:
                break
            
             if event1.isSet():
                
                 event2.clear() # 设置内部标志为假
                
                time.sleep(0.008)
                print thread1.dict["qq"]
                
                 event2.set() # 设置内部标志为真,唤醒等待线程
                print "data is not used"
                
                loop -= 1
        except Exception, e:
            print e
            thread1.stop()
            sys.exit(1)
         
    thread1.stop()
    
    print "[main] main is finished"
    
    return
 
if __name__ == '__main__':
    test()

猜你喜欢

转载自blog.csdn.net/zklth/article/details/8709472
今日推荐