Semaphore:
Semaphore is an abstract data type managed by the operating system, which is used to synchronize the use of shared resources in multiple threads. In essence, a semaphore is an internal data used to indicate how many concurrent reads can be made to the current shared resource.
In threading module Semaphore class The semaphore object is implemented, 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.
Function and application:
It is mainly used in database applications, such as connecting to the database and limiting the number of simultaneous connections, such as database connection pool.
As shown in the above figure, define a run method, where parameter n represents the output thread, and x is used to control the extension time of the output thread, where semaphore = threading, seamless (5), and the number five is used to control that the number of threads output each time cannot exceed 5
Conditional variable:
The condition object provided by Python provides support for complex thread synchronization problems. Condition is called a condition variable. In addition to the acquire and release methods similar to Lock, it also provides wait and notify methods.
Construction method:
import threading # A mutex or reentrant lock can be passed in cond = threading.Condition()
Instance method:
acquire([timeout])/release(): Call the corresponding method of the associated lock. wait([timeout]): Calling this method will cause the thread to enter Condition The waiting pool waits for notification and releases the lock. The thread must be locked before use, or an exception will be thrown. notify(): Calling this method will select a thread from the waiting pool and notify it. The thread receiving the notification will call it automatically acquire()Attempt to obtain a lock (enter the lock pool); Other threads are still waiting in the pool. Calling this method will not Release the lock. The thread must be locked before use, or an exception will be thrown. notifyAll(): Calling this method will notify all threads in the wait pool that they will enter the lock pool Try to get a lock. Calling this method does not release the lock. The thread must be locked before use, or an exception will be thrown
Find a case from the Internet to help understand:
Producer and consumer model, take eating hot pot as an example: there are 10 pieces of meat in a plate of old meat slices. After eating, add them to the pot again
Producer: add old meat slices to the pot, one plate at a time (10 pieces);
Consumer: eat cooked meat slices, mei eat one slice, and the number of meat slices will be reduced by one until finished;
# Import thread module import threading import time # Create condition variable condition con = threading.Condition() meat_num = 0 def thread_consumers(): # Condition variable condition thread lock con.acquire() # global variable declaration keyword global global meat_num meat_num = 0 # Wait until the meat slices are cooked con.wait() while True: print("I'll have a piece of meat...") meat_num -= 1 print("Quantity of remaining meat slices:%d"%meat_num) time.sleep(0.5) if meat_num == 0: # When the meat slices are eaten up, inform the boss to add meat slices print("Boss, another slice of old meat...") con.notify() # The meat is eaten up. Wait for the meat con.wait() # Condition variable condition thread releases lock con.release() def thread_producer(): # Condition variable condition thread lock con.acquire() # global variable declaration keyword global global meat_num # The sliced meat is ripe and ready to eat meat_num = 10 print("The sliced meat is ripe and ready to eat...") con.notify() while True: # Blocking function, waiting for the notification that the meat slice is finished con.wait() meat_num = 10 # After adding meat slices, you can continue to eat print("Meat slices added successfully! Current number of meat slices:%d"%meat_num) time.sleep(1) con.notify() con.release() if __name__ == "__main__": # Create and initialize threads t1 = threading.Thread(target=thread_producer) t2 = threading.Thread(target=thread_consumers) # Start thread -- pay attention to the start sequence of threads. The start sequence is very important t2.start() t1.start() # Block the main thread and wait for the child thread to end t1.join() t2.join() print("The program is over!")
Event:
Event: the mechanism of event processing: a built-in Flag is defined globally. If the Flag value is False, when the program executes event If the Flag value is True, then event The wait method is no longer blocked.
Event is actually a simplified version of Condition. Event has no lock and cannot put the thread into synchronization blocking state.
Event()
-
set(): set the flag to True and notify all threads in the waiting blocking state to resume running state.
-
clear(): set the flag to False.
-
wait(timeout): if the flag is True, it will be returned immediately. Otherwise, the thread will be blocked to the waiting blocking state and wait for other threads to call set().
-
isSet(): gets the built-in flag status and returns True or False.
Case:
Small partners a and b are ready when they receive the notification event When set (), threads a and b will be executed
# coding:utf-8 import threading import time event = threading.Event() def chihuoguo(name): # Wait for the event and enter the wait blocking state print '%s Already started' % threading.currentThread().getName() print 'buddy %s Has entered the dining state!'%name time.sleep(1) event.wait() # Enter the running state after receiving the event print '%s Got the notice.' % threading.currentThread().getName() print 'buddy %s Start eating!'%name # Set thread group threads = [] # Create a new thread thread1 = threading.Thread(target=chihuoguo, args=("a", )) thread2 = threading.Thread(target=chihuoguo, args=("b", )) # Add to thread group threads.append(thread1) threads.append(thread2) # Open thread for thread in threads: thread.start() time.sleep(0.1) # Send event notification print 'The main thread informs the child to eat!' event.set()
Operation results:
Thread-1 Already started buddy a Has entered the dining state! Thread-2 Already started buddy b Has entered the dining state! The main thread informs the child to eat! Thread-1 Got the notice. buddy a Start eating! Thread-2 Got the notice. buddy b Start eating!