Semaphores, conditional variables, events

Posted by cemeteryridge on Sun, 09 Jan 2022 17:46:44 +0100

Semaphore

Semaphore class in threading module implements semaphore object, which can be used to control the number of threads obtaining resources. The acquire() and release() methods can be used as the context manager of the with statement. The acquire() method is called when entering, and release() is called when exiting.

Semaphore is similar to Lock, but semaphore allows you to specify a maximum number of processes to access resources. Just as the resource has multiple doors, each door has a Lock. A process accesses resources, locks doors, and other doors can be used. But if all the doors are used, you have to wait for a process to release the Lock.

 

'''Semaphore'''
import threading
import time

def run(n):
    semaphore.acquire()
    print("Thread:",n)
    time.sleep(1)
    semaphore.release()

if __name__ == '__main__':
    #Set semaphore
    semaphore = threading.Semaphore(2)#Every 2 simultaneous execution
    for i in range(5):
        t = threading.Thread(target=run,args=(i,))
        t.start()

Operation results:

Thread: 0 thread: 1

Thread: 2 thread: 3

Thread: 4 thread: 5

Thread: 6 thread: 7

Thread: 8 thread: 9

Conditional variable

Condition is called a condition variable. In addition to the acquire and release methods similar to Lock, it also provides wait and notify methods. The thread first acquires a condition variable and then judges some conditions. If the conditions are not met, wait; If the conditions are met, perform some processing. After changing the conditions, wake up other threads through the notify method. Other threads in the wait state will re judge the conditions after receiving the wake-up. This process is repeated continuously to solve the complex synchronization problem.

'''Conditional variable'''
import threading
import time

def run(n):
    con.acquire()
    print(f'Thread:{n}')
    con.notify()#Wake up other threads when starting this thread
    print(f'Thread:{n}Hang')
    con.wait()#Make it wait
    time.sleep(1)
    print(f'Thread:{n}Restart')
    con.notify()
    con.release()

#Simultaneous operation
if __name__ == '__main__':
    con = threading.Condition()#Conditional variable
    for i in range(10):
        t = threading.Thread(target=run,args=(i,))
        t.start()
Thread: 0
 Thread: 0 suspended
 Thread: 1
 Thread: 1 suspended
 Thread: 0 started again
 Thread: 2
 Thread: 2 suspended
 Thread: 3
 Thread: 3 suspended
 Thread: 4
 Thread: 4 suspended
 Thread: 5
 Thread: 5 suspended
 Thread: 6
 Thread: 6 pending
 Thread: 5 restart
 Thread: 8
 Thread: 8 pending
 Thread: 9
 Thread: 9 suspended
 Thread: 1 starts again
 Thread: 2 starts again
 Thread: 3 restart
 Thread 4: restart
 Thread: 7
 Thread: 7 pending
 Thread: 6 restart
 Thread: 8 restart
 Thread: 9 starts again

Event

Python provides an event object for inter thread communication. It is a signal flag set by threads. If the signal flag bit is true, other threads wait until the signal contacts. Event objects can keep threads synchronized by notifying operations, and can realize thread synchronization operations in different processes.

The Event object implements a simple thread communication mechanism. It provides setting signal set(), clearing signal clear(), waiting for wait(), etc. to realize the communication between threads.

'''event'''
import threading
import time
def car():
    #Loop to detect if the event is set
    while True:
        if event.is_set():#If the event is set
            print('Trolley travel')
        else:
            print('Trolley stop')
            event.wait()#wait if the event is cleared

def set_event():
    #Loop, always let it set / cancel events
    while True:
        event.set()#Set event
        time.sleep(1)  #In this 1 second, the 'trolley travel' will be printed repeatedly because thread car1 has been detecting
        event.clear()  #Clear event
        time.sleep(1)  #The printing will not be repeated within 1 second because thread car1 is wait ing
        #Then cycle to the beginning, the event continues to be set, and continue to print 'trolley travel'

if __name__ == '__main__':
    event = threading.Event()
    #Thread start, two threads are started at the same time
    car1 = threading.Thread(target=car)
    car1.start()
    set1 = threading.Thread(target=set_event)
    set1.start()

Topics: Python