Semaphore
Semaphores are multiple locks that allow multiple threads to change data at the same time, while mutually exclusive locks allow only one thread to change data at the same time.
Relationship between Python semaphores and mutexes
A special use of semaphores is mutex. Mutex is a semaphore with an initial value of 1, which can realize the mutex access of data and resources.
Python semaphore usage syntax:
import threading sem = threading.Semaphore(3) sem.acquire() sem.release()
Python multithreaded semaphore usage
Using threading Semaphore semaphore control multithreading
import threading import time def run(n): semaphore.acquire() time.sleep(1) print("thread:%s is running" % n) semaphore.release() if __name__ == '__main__': print("111") semaphore = threading.Semaphore(3) #Up to 3 threads are allowed to run at the same time for i in range(3): t = threading.Thread(target=run, args=(i,)) t.start() while threading.active_count() != 1: pass else: print('----all threads done---')
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, notify other threads through the notify method. Other threads in wait state will re judge the conditions after receiving the notification. This process is repeated continuously to solve the complex synchronization problem.
It can be considered that the Condition object maintains a lock (Lock/RLock) and a waiting pool. The thread obtains the Condition object through acquire. When calling the wait method, the thread will release the lock inside the Condition and enter the blocked state. At the same time, the thread will be recorded in the waiting pool. When the notify method is called, the Condition object selects a thread from the waiting pool and tells it to call the acquire method to try to get the lock.
In addition to the notify method, the Condition object also provides the notifyAll method, which can notify all threads in the waiting pool to try to acquire the internal lock. Due to the above mechanism, the thread in the waiting state can only wake up through the notify method. Therefore, the function of notifyAll is to prevent a thread from being silent forever.
The classical problem of demonstrating conditional variable synchronization is the producer Consumer problem: suppose a group of producers and consumers interact with products through a market. The producer's "strategy" is to produce 100 products and put them on the market if there are less than 1000 products left in the market, while the Consumer's "strategy" is to consume 3 products if there are more than 100 products left in the market. The code to solve the problem between producers and consumers with Condition is as follows:
import threading import time class Producer(threading.Thread): def run(self): global count while True: if con.acquire(): if count > 1000: con.wait() else: count = count+100 msg = self.name+' produce 100, count=' + str(count) print msg con.notify() con.release() time.sleep(1) class Consumer(threading.Thread): def run(self): global count while True: if con.acquire(): if count < 100: con.wait() else: count = count-3 msg = self.name+' consume 3, count='+str(count) print msg con.notify() con.release() time.sleep(1) count = 500 con = threading.Condition() def test(): for i in range(2): p = Producer() p.start() for i in range(5): c = Consumer() c.start() if __name__ == '__main__': test()
Python Event
As with processes, a key feature of threads is that each thread runs independently and its state is unpredictable. If other threads in the program need to determine their next operation by judging the state of a thread, the thread synchronization problem will become very difficult. To solve these problems, we need to use the Event object in the threading library. Object contains a signal flag that can be set by the thread, which allows the thread to wait for certain events to occur. Initially, the signal flag in the Event object is set to false. If a thread waits for an Event object and the flag of the Event object is false, the thread will be blocked until the flag is true. If a thread sets the signal flag of an Event object to true, it will wake up all threads waiting for the Event object. If a thread waits for an Event object that has been set to true, it will ignore the Event and continue to execute.
Event several methods:
event.isSet(): return event Status value of; event.wait(): If event.isSet()==False Thread will be blocked; event.set(): set up event The status value of is True,All threads blocking the pool are activated into a ready state,Waiting for operating system scheduling; event.clear(): recovery event The status value of is False.
give an example:
from threading import Thread,Event import time event=Event() def light(): print('The red light is on') time.sleep(3) event.set() #The green light is on def car(name): print('vehicle%s Waiting for the green light' %name) event.wait() #When the light is green, event is False until event Set() sets its value to True to continue running print('vehicle%s current' %name) if __name__ == '__main__': # traffic lights t1=Thread(target=light) t1.start() # vehicle for i in range(10): t=Thread(target=car,args=(i,)) t.start()
Task example
Get the current time in the first thread, judge the current time for 3 seconds, and then trigger the "event" object. In another thread, it is used as the judgment variable for the end of the math exam, otherwise it is always in the exam and printed.
import threading # Import thread class import time # Import time class import datetime # Import datetime class class eventthread(threading.Thread): # Defines an event listening class that inherits from the Thread class def __init__(self): # Define construction method super(eventthread, self).__init__() # Override the constructor of Thread class def run(self): # Override the run method of the Thread class for i in range(3): # The for statement loops for 3 seconds time1 = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') print(time1) # Specifies that the output format displays the current time time.sleep(1) # Pause for 1 second event.set() # Set event response class mythread(threading.Thread): # Inherited from Thread class def __init__(self): # Define construction method super(mythread, self).__init__() # Override the constructor of Thread class def run(self): # Override run method while True: # Loop to determine whether the event responds print("In the exam") # If the event does not respond, the information of "in the exam" will be output time.sleep(1) # Pause for 1 second if event.is_set(): print("The exam is over!") # If the event responds, the information of "examination end" will be output break # Jump out of loop if __name__ == '__main__': # Create main thread event = threading.Event() # Initialize object et = eventthread() # Initialize a thread object mt = mythread() # Initialize a thread object et.start() # Start thread mt.start() # Start thread