Thread synchronization
Thread work, when one thread to access data through a certain technology to ensure that other threads can not access the data until the end of the previous thread access
Event Event
Setting a flag in the internal process, code execution is controlled by varying the flag of whether to wait, this is the event flag instance.
Examples of events required threading module class Event to create.
first name | meaning |
---|---|
set() | Examples of events is set to True |
clear() | Examples of events is set to False |
is_set() | Determine whether the event instance is True |
wait(timeout=None) | Set wait event instance, None indicates an infinite wait. Wait for a timeout returns False |
Encountered during code execution event.wait () occurs blocked, waiting for event programming True.
Illustration, red and green traffic light switch, awaiting a signal for an automobile traffic, the car is set to pass a thread, another thread is switched traffic lights
from threading import Event,Thread
import logging
import time
FORMAT='%(asctime)s %(threadName)s %(thread)d %(message)s'
logging.basicConfig(format=FORMAT,level=logging.INFO)
def car(event):
logging.info('车子在等红灯')
event.wait()
logging.info('车子通过')
def deng(event):
for i in range(5,0,-1):
logging.info('现在是红灯,还有%ds'%i)
time.sleep(1)
event.set()
logging.info('现在是绿灯')
event=Event()
c=Thread(target=car,args=(event,))
d=Thread(target=deng,args=(event,))
c.start()
d.start()
#输出结果如下
2019-07-04 18:45:52,985 Thread-1 123145474813952 车子在等红灯
2019-07-04 18:45:52,985 Thread-2 123145480069120 现在是红灯,还有5s
2019-07-04 18:45:53,987 Thread-2 123145480069120 现在是红灯,还有4s
2019-07-04 18:45:54,991 Thread-2 123145480069120 现在是红灯,还有3s
2019-07-04 18:45:55,993 Thread-2 123145480069120 现在是红灯,还有2s
2019-07-04 18:45:56,994 Thread-2 123145480069120 现在是红灯,还有1s
2019-07-04 18:45:57,999 Thread-2 123145480069120 现在是绿灯
2019-07-04 18:45:57,999 Thread-1 123145474813952 车子通过
from threading import Event,Thread
import logging
import datetime
FORMAT='%(asctime)s %(threadName)s %(thread)d %(message)s'
logging.basicConfig(format=FORMAT,level=logging.INFO)
def add(x,y):
logging.info(x+y)
class Timer:
def __init__(self,interval,fn,*args,**kwargs):
self.interval=interval
self.fn=fn
self.args=args
self.kwargs=kwargs
self.event=Event() ##为一个Timer类的实例创建一个属性event,该属性为事件实例,初始为False。
def start(self):
t=Thread(target=self.__run)
t.start()
def cancel(self):
self.event.set()
def __run(self):
start=datetime.datetime.now()
logging.info('waiting')
self.event.wait(self.interval) ##遇到event.wait发生阻塞,等待Timer类的实例属性event变为True。超时时间为self.interval
if not self.event.is_set():##如果self.event是False,则执行self.fn函数
self.fn(*self.args,**self.kwargs)
delta=(datetime.datetime.now()-start).total_seconds()
logging.info('finshed {}'.format(delta))
self.event.set()
T=Timer(10,add,4,50) #依据类Timer实例化一个对象T
T.start()#调用实例T的start方法生成一个子线程,该子线程运行self__run方法
e=Event()#创建一个事件实例e
e.wait(4)#发生阻塞,等待超时,继续执行后面的代码
T.cancel() #将实例t的event属性修改为Ture
print('end')
#输出结果
2019-07-04 22:43:39,839 Thread-1 123145402576896 waiting
#(此处等待4秒,如果主线程不执行T.cancel()则等待10秒之后输出add函数)
2019-07-04 22:43:43,843 Thread-1 123145402576896 finshed 4.003959
end
Examples of Timer T is the example we create a class instance, not threads.
Lock Lock
Any time there is a shared resource competition can be locked controlled to ensure that only one user access to resources.
Example: 10 workers generate Cup 1000, 10 workers is 10 sub-threads. The cup is a list of the number of cups, the list needs to be accessed and modified before 10 workers each production. If there is no lock control, may cause the list is already full 1000, but some workers get a list of the lag is less than 1000, still continues to produce.
from threading import Lock,Thread
import logging
import time
FORMAT='%(asctime)s %(threadName)s %(thread)d %(message)s'
logging.basicConfig(format=FORMAT,level=logging.INFO)
cups=[]
lock=Lock()
def worker(count):
logging.info('start work...')
flag=False
while True:
lock.acquire()
if len(cups) >=count:
flag=True
if not flag:
time.sleep(0.001)
cups.append(1)
lock.release()
if flag:
break
logging.info('work finshed count={}'.format(len(cups)))
for i in range(10):
Thread(target=worker,args=(100,)).start()
死锁
Between locking and unlocking some code execution, if the code to throw an exception then it can not be unlocked, and this led to deadlock.
The lock may be repeated RLock
Internal RLock maintains a Lock and a counter variable, RLock a thread can lock multiple acquire () without blocking, counter records the number of acquire. Until a lock for the thread will acquire all of which are release, other threads can acquire a lock.
Scenario:
The main thread is for your process there will be some more complex code logic processes, such as many layers of function calls, but in fact these functions need to be locked to protect data access.
This may be repeated several times lock, so you can use rlock multiple lock, unlock, until eventually the lock is released
and if an ordinary lock, another when you have a lock function A, it is called internally function B, if B will lock on the inside with a lock, then this situation can lead to a deadlock. The rlock can solve this problem
condition
from threading import Event,Thread,Condition,active_count,enumerate
import logging
import random
import time
FORMAT='%(asctime)s %(threadName)s %(thread)d %(message)s'
logging.basicConfig(format=FORMAT,level=logging.INFO)
class Dis:
def __init__(self):
self.data=None
self.event=Event()
self.cond=Condition() #2
def pro(self,total):
for i in range(total):
data=random.randint(0,100)
# logging.info(data)
# self.data=data
with self.cond:
logging.info(data)
self.data=data
self.cond.notify_all()
logging.info('pro working event is {}'.format(self.event.is_set()))
self.event.wait(1)
self.event.set()
logging.info('pro finshed event is {}'.format(self.event.is_set()))
def con(self):
while not self.event.is_set():
logging.info('xunhuan')
# logging.info('received {}'.format(self.data))
# self.data=None
with self.cond:
self.cond.wait()
logging.info('received {}'.format(self.data))
self.data=None
self.event.wait(0.5)
logging.info('con received {}'.format(self.event.is_set()))
d=Dis()
Thread(target=d.con,name='con',daemon=True).start()
Thread(target=d.pro,args=(5,),name='pro').start()
print(active_count(),enumerate())