We usually use multithreading to run individual operations concurrently , But sometimes you need to be in two or more threads Synchronous operation . stay Python in , There are many ways to synchronize threads , Include Event、Condition and Barrier
caller It can be used set() and clear() Method to control this flag , Other threads have access to wait() Pause , Until this flag is set
import logging
import time
from threading import Thread, Event
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s-%(asctime)s-%(message)s')
def wait_for_start_work(e_start_work: Event, name: str):
logging.debug(f'{
name} Waiting for work ...')
e_start_work.wait() # Will block until the event is set
while e_start_work.is_set():
logging.debug(f'{
name} I am working ...')
time.sleep(1)
else:
logging.debug(f'{
name} After work !!!!')
def wait_for_start_work_timeout(e_start_work: Event, name: str):
logging.debug(f'{
name} Waiting for work ...')
event_is_set = e_start_work.wait(timeout=1) # Wait the most 1 second
if not event_is_set:
logging.debug(f'{
name} No notice to work yet , I did it myself ..')
else:
logging.debug(f'{
name} I am working ...')
if __name__ == '__main__':
e = Event()
for i in range(2):
t = Thread(target=wait_for_start_work, args=(e, f' staff {
i}'))
t.start()
t_xiaowang = Thread(target=wait_for_start_work_timeout, args=(e, f' Responsible Xiao Wang '))
t_xiaowang.start()
time.sleep(2)
logging.info(' The leader said : It 's working !!!')
e.set()
time.sleep(2)
logging.info(' The leader said : Off work !!!')
e.clear()
result
DEBUG-2022-06-24 10:14:07,076- staff 0 Waiting for work ...
DEBUG-2022-06-24 10:14:07,076- staff 1 Waiting for work ...
DEBUG-2022-06-24 10:14:07,077- Responsible Xiao Wang Waiting for work ...
DEBUG-2022-06-24 10:14:08,091- Responsible Xiao Wang No notice to work yet , I did it myself ..
INFO-2022-06-24 10:14:09,077- The leader said : It 's working !!!
DEBUG-2022-06-24 10:14:09,077- staff 0 I am working ...
DEBUG-2022-06-24 10:14:09,077- staff 1 I am working ...
DEBUG-2022-06-24 10:14:10,086- staff 0 I am working ...
DEBUG-2022-06-24 10:14:10,086- staff 1 I am working ...
INFO-2022-06-24 10:14:11,085- The leader said : Off work !!!
DEBUG-2022-06-24 10:14:11,101- staff 0 After work !!!!
DEBUG-2022-06-24 10:14:11,101- staff 1 After work !!!!
Condition Used a Shared resource lock , Allow multiple threads to wait for resource updates .
import logging
import time
from threading import Thread, Condition
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s-%(asctime)s-%(message)s')
def wait_for_start_work(c_start_work: Condition, name: str):
logging.debug(f'{
name} Waiting for work ...')
with c_start_work:
c_start_work.wait() # Wait until you receive the notice
logging.debug(f'{
name} I am working ...')
def wait_for_start_work_timeout(c_start_work: Condition, name: str):
logging.debug(f'{
name} Waiting for work ...')
with c_start_work:
c_start_work.wait(timeout=1) # Wait the most 1 second
logging.debug(f'{
name} No notice to work yet , I did it myself ..')
if __name__ == '__main__':
c = Condition()
for i in range(2):
t = Thread(target=wait_for_start_work, args=(c, f' staff {
i}'))
t.start()
t_xiaowang = Thread(target=wait_for_start_work_timeout, args=(c, f' Responsible Xiao Wang '))
t_xiaowang.start()
time.sleep(2)
with c: # Use here with To get and Condition Associated lock , It can also show the use of acquire() and release() Method
logging.info(' The leader said : It 's working !!!')
c.notify_all() # notice wait State of all threads
# c.notify(2) # notice 2 individual wait Thread in state
result
DEBUG-2022-06-24 10:39:00,615- staff 0 Waiting for work ...
DEBUG-2022-06-24 10:39:00,616- staff 1 Waiting for work ...
DEBUG-2022-06-24 10:39:00,616- Responsible Xiao Wang Waiting for work ...
DEBUG-2022-06-24 10:39:01,630- Responsible Xiao Wang No notice to work yet , I did it myself ..
INFO-2022-06-24 10:39:02,628- The leader said : It 's working !!!
DEBUG-2022-06-24 10:39:02,628- staff 0 I am working ...
DEBUG-2022-06-24 10:39:02,629- staff 1 I am working ...
Barrier Will establish a rendezvous point , When the specified number of threads reaches this point, they will be released
import logging
import time
import threading
from threading import Thread, Barrier
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s-%(asctime)s-%(message)s')
def wait_for_start_work(b_start_work: Barrier):
logging.debug('{} Wait for others to arrive ..'.format(threading.current_thread().name))
b_start_work.wait() # It will be blocked until it is released
logging.debug('{} I am working ...'.format(threading.current_thread().name))
if __name__ == '__main__':
b = Barrier(3) # Assembly point of three threads
for i in range(6):
t = Thread(target=wait_for_start_work, name=f' staff {
i}',args=(b, ))
t.start()
time.sleep(1)
result
DEBUG-2022-06-24 11:01:18,710- staff 0 Wait for others to arrive ..
DEBUG-2022-06-24 11:01:19,726- staff 1 Wait for others to arrive ..
DEBUG-2022-06-24 11:01:20,738- staff 2 Wait for others to arrive ..
DEBUG-2022-06-24 11:01:20,739- staff 2 I am working ...
DEBUG-2022-06-24 11:01:20,739- staff 1 I am working ...
DEBUG-2022-06-24 11:01:20,739- staff 0 I am working ...
DEBUG-2022-06-24 11:01:21,755- staff 3 Wait for others to arrive ..
DEBUG-2022-06-24 11:01:22,768- staff 4 Wait for others to arrive ..
DEBUG-2022-06-24 11:01:23,768- staff 5 Wait for others to arrive ..
DEBUG-2022-06-24 11:01:23,768- staff 5 I am working ...
DEBUG-2022-06-24 11:01:23,768- staff 3 I am working ...
DEBUG-2022-06-24 11:01:23,768- staff 4 I am working ...