One, multithreading synchronization
Because CPython's Python interpreter executes in single-threaded mode, Python multithreading does not work well with multi-core CPU resources at many times. Multiple processes are recommended in most cases.
Python's multithreaded synchronization is essentially the same as other languages, including:
Lock & Rlock: Used to secure access to multiple shared resources for multithreading.
Semaphore: The upper limit, such as a resource pool, used to ensure that a certain resource is accessed multi-threaded.
Event: Is the simplest way to communicate between threads, one thread can send signals, and other threads receive signals to perform operations.
Second, the example
1) Lock & Rlock
The lock object's state can be locked and unlocked
Use Acquire () to set the locked state;
Use release () to set the unlocked state.
If the current state is unlocked, acquire () changes the status to locked and then returns immediately. When the state is locked, acquire () is blocked until another thread calls release () to change the state to unlocked, and then acquire () to make the status locked again.
Lock.acquire (Blocking=true, timeout=-1), blocking parameter indicates whether the current thread is blocked from waiting, and timeout indicates the wait time when blocking. If lock is successfully obtained, the acquire () function returns True, otherwise returns false if the lock has not been obtained by False,timeout timeout.
Instance: (Ensure that only one thread can access a shared resource)
Copy Code code as follows:
Import threading
Import time
num = 0
Lock = Threading. Lock ()
def func (ST):
Global num
Print (Threading.currentthread (). GetName () + ' try to acquire the lock ')
If Lock.acquire ():
Print (Threading.currentthread (). GetName () + ' acquire the lock. ')
Print (Threading.currentthread (). GetName () + ":%s"% str (num))
num + + 1
Time.sleep (ST)
Print (Threading.currentthread (). GetName () + ' release the lock. ' )
Lock.release ()
T1 = Threading. Thread (Target=func, args= (8,))
T2 = Threading. Thread (Target=func, args= (4,))
T3 = Threading. Thread (Target=func, args= (2,))
T1.start ()
T2.start ()
T3.start ()
Results:
The difference between Rlock and lock is that the owner and the number of recursive layers of the current lock are recorded in the Rlock in addition to the state locked and unlocked, allowing Rlock to be acquire () multiple times by the same thread.
2) Semaphore
Semaphore manages a built-in counter,
Built-in counter-1 whenever acquire () is invoked;
Built-in counter +1 when calling release ();
The counter cannot be less than 0, and when the counter is 0 o'clock, acquire () blocks the thread until the other thread invokes release ().
Instance: (at the same time only 2 threads can get semaphore, that is, you can limit the maximum number of connections to 2):
Copy Code code as follows:
Import threading
Import time
Semaphore = Threading. Semaphore (2)
def func ():
If Semaphore.acquire ():
For I in range (5):
Print (Threading.currentthread (). GetName () + ' get semaphore ')
Semaphore.release ()
Print (Threading.currentthread (). GetName () + ' release semaphore ')
For I in range (4):
T1 = Threading. Thread (Target=func)
T1.start ()
Results:
3) Event
The event contains a flag bit that is false at the initial time.
You can use Set () to set it to true;
or use Clear () to reset it to false;
You can use Is_set () to check the status of the flag bit;
Another most important function is wait (timeout=none), which blocks the current thread until the internal flag bit of the event is set to TRUE or the timeout timeout. If the internal flag bit is true, the wait () function understands the return.
Instance: (Communication between threads)
Copy Code code as follows:
Import logging
Import threading
Import time
Logging.basicconfig (level=logging. DEBUG,
Format= "(% (threadname) -10s:% (message) s",
)
def wait_for_event_timeout (E, T):
"" "Wait t seconds and then timeout" ""
While not E.isset ():
Logging.debug ("Wait_for_event_timeout starting")
Event_is_set = e.wait (t)
Logging.debug ("Event set:%s"% event_is_set)
If Event_is_set:
Logging.debug ("Processing event")
Else
Logging.debug ("Doing other work")
E = Threading. Event ()
T2 = Threading. Thread (name= "Nonblock",
Target=wait_for_event_timeout,args= (E, 2))
T2.start ()
Logging.debug ("Waiting before calling Event.set ()")
Time.sleep (7)
E.set ()
Logging.debug ("Event is set")
Run Result:
Third, other
1) Thread Local variables
The value of a thread-local variable is thread-dependent and differs from global variables. The use is very simple as follows:
Copy Code code as follows:
MyData = Threading.local ()
mydata.x = 1
2) Use the WITH keyword instead of manual call Acquire () and release () for Lock,semaphore,condition.