ArticleDirectory
- Question proposal
- Mutex lock Synchronization
- Synchronization Blocking
Question proposal
In the preceding example, each thread is independent of each other and has no relationship with each other. Now let's assume that there is a global count num. Each thread obtains the global count, processes it according to num, and adds num to 1. It is easy to write suchCode:
# Encoding: UTF-8
Import Threading
Import Time
Class Mythread (threading. Thread ):
Def Run (Self ):
Global Num
Time. Sleep (1)
Num = num + 1
MSG = self. Name + ' Set num ' + STR (Num)
Print MSG
Num = 0
Def Test ():
For I In Range (5 ):
T = mythread ()
T. Start ()
If _ Name __ = ' _ Main __ ' :
Test ()
However, the running result is incorrect:
Thread-5 set num to 2
Thread-3 set num to 3
Thread-2 set num to 5
Thread-1 Set num to 5
Thread-4 set num to 4
The cause of the problem is that the access to the same resource by multiple threads is not controlled, and the data is damaged, which makes the running result of the thread unpredictable. This phenomenon is called "thread unsafe ".
Mutex lock Synchronization
The above example introduces the most common problem of multi-threaded programming: data sharing. When multiple threads modify a shared data, synchronous control is required.
Thread Synchronization ensures secure access to competing resources by multiple threads. The simplest synchronization mechanism is to introduce mutex locks. The mutex lock introduces a status for the resource: Locked/unlocked. When a thread wants to change the shared data, it first locks it. At this time, the resource status is "locked" and other threads cannot be changed until the thread releases resources, changes the resource status to "Unlocked", and other threads can lock the resource again. The mutex lock ensures that only one thread writes data at a time, thus ensuring data correctness in the case of multiple threads.
The threading module defines the lock class to facilitate lock handling:
#Create lock
Mutex = threading. Lock ()
#Lock
Mutex. Acquire ([timeout])
#Release
Mutex. Release ()
The locking method acquire can have an optional timeout parameter timeout. If timeout is set, you can use the returned value to determine whether the lock is obtained after the timeout, so that you can perform other processing.
The code for using mutex to implement the above example is as follows:
Import Threading
Import Time
Class Mythread (threading. Thread ):
Def Run (Self ):
Global Num
Time. Sleep (1)
If Mutex. Acquire (1 ):
Num = num + 1
MSG = self. Name + ' Set num ' + STR (Num)
Print MSG
Mutex. Release ()
Num = 0
Mutex = threading. Lock ()
Def Test ():
For I In Range (5 ):
T = mythread ()
T. Start ()
If _ Name __ = ' _ Main __ ' :
Test ()
Running result:
Thread-3 set num to 1
Thread-4 set num to 2
Thread-5 set num to 3
Thread-2 set num to 4
Thread-1 Set num to 5
As you can see, after the mutex lock is added, the running results are consistent with expectations.
Synchronization Blocking
When a thread calls the lock's acquire () method to obtain the lock, the lock enters the "locked" state. Only one thread can obtain the lock at a time. If another thread tries to obtain the lock at this time, the thread changes to the "blocked" state, known as "synchronization blocking" (see the basic concept of multithreading ).
The lock enters the "Unlocked" state after the locks are released by the release () method called by the thread that owns the lock. Thread SchedulingProgramSelect a thread in the synchronization blocking State to obtain the lock and bring the thread into the running state.
The most basic content of mutex is this. The next section will discuss the rlock and deadlock issues.