python learning notes 4

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

Keywords: Python event

Added by RichterBelmont on Sun, 09 Jan 2022 18:04:56 +0200