Synchronous 12, thread

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.

Here Insert Picture Description

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())
Published 40 original articles · won praise 2 · Views 2055

Guess you like

Origin blog.csdn.net/weixin_42155272/article/details/94663497