In this paper, the use of multi-threading in Python is described in detail, and it is widely used in Python program design. Share it for everyone's reference. The specific analysis is as follows:
The operation of multithreading in Python can be implemented using the thread and threading modules, where the thread module has been renamed _thread in Py3 and is no longer recommended for use. While the threading module is encapsulated on the thread, it is also recommended to use multithreaded modules, this article is mainly based on the threading module is introduced. In some versions, the thread module may not exist and you will use dump_threading instead of the threading module.
One, thread creation
Each thread in the threading module is a thread object, there are two ways to create a thread, one is to pass the function to the thread object, the other is to inherit from the thread, and then rewrite the Run method (it is not like Java).
The following two methods are used to create a single thread and execute the
Import random, Threadingdef threadfunction (): For i in range: print ' threadfuction-%d '%i time.sleep ( Random.randrange (0,2)) class ThreadClass (threading. Thread): def __init__ (self): threading. Thread.__init__ (self); def run (self): for i in range: print ' threadclass-%d '%i time.sleep (Random.randrange (0,2)) if __name__ = = ' __main__ ': tfunc = Threading. Thread (target = threadfunction); TCls = ThreadClass () Tfunc.start () Tcls.start ()
The execution results are as follows, and you can see that two threads are printing alternately. As for blank lines and a row of multiple outputs, the PY print is not thread-safe, and after the current thread prints a portion of the content, it is pre-printed with print in another thread before it is ready for a line break, and other content is printed before wrapping.
Threadfuction-0threadfuction-1threadfuction-2threadclass-0threadfuction-3threadclass-1threadfuction-4threadc Lass-2threadclass-3threadclass-4threadfuction-5threadclass-5threadclass-6threadclass-7threadclass-8threadf Uction-6threadclass-9threadfuction-7threadfuction-8threadfuction-9
The constructor for the thread class is defined as follows
Class Threading. Thread (Group=none, Target=none, Name=none, args= (), kwargs={})
Group: Reserved for Threadgroup expansion use, generally useless
Target: The task function name of the new thread
Name: thread name, generally not used
Args:tuple parameters
Kwargs:dictionary parameters
The member variables and functions of the thread class are as follows
Start () starts a thread
Run () thread execution body, also the content that is generally to be rewritten
Join ([timeout]) waits for thread to end
Name Thread Name
Ident thread ID
Daemon whether to daemon threads
IsAlive (), is_alive () thread is alive
Get&set method for GetName (), SetName () name
Get&set method for Isdaemon (), Setdaemon () daemon
The daemon thread here is not a concept with the daemon in Linux. This is when all daemons exit the main program, or even if the thread task is not finished, as long as it is not the daemon, it will exit with the master program. While the daemon definition in Linux is the opposite, the daemon is out of the parent process and does not exit with the end of the parent process.
Second, thread synchronization
thread synchronization is a core problem in multi-threading, and the threading module has good support for thread synchronization, including thread-specific data, semaphore, mutex, condition variables and so on .
1. Thread-specific data
In short, thread-specific data is a global variable that the thread holds on its own, and changes between the threads do not affect each other.
The threading module uses the local () method to generate a thread-independent object, such as the following, where sleep (1) is used to ensure that the child thread runs out of the next statement before running.
data = Threading.local () def threadfunction (): global Data data.x = 3 print threading.currentthread (), data.x If __name__ = = ' __main__ ': data.x = 1 tfunc = Threading. Thread (target = threadfunction). Start (); Time.sleep (1) print threading.current_thread (), data.x
3<_mainthread (Mainthread, started 35888) > 1
As you can see on the output, the changes to data.x in Thread-1 do not affect the value data.x in the main thread.
2. Mutual exclusion Lock
There are two types of locks defined in threading: Threading. Lock and Threading.rlock. The difference between the two is that the latter is a reentrant lock, that is, repeating lock within a thread does not deadlock the same lock, which is the same as the concept of pthread_mutex_recursive in POSIX, which is a recursive lock.
The API for mutexes is simple, with only three functions ———— assigning locks, locking, unlocking.
Threading. Lock () assigns a mutex lock
Acquire ([blocking=1]) is locked (blocking or non-blocking, which is equivalent to Try_lock when not blocked, by returning false to indicate that it has been locked by another thread. )
Release () Unlock
The use of mutexes is illustrated below with an example. In the previous example, multi-threaded print creates a confusing output, where a mutex is used to ensure that each line must have only one output.
def threadfunction (ARG): While True: lock.acquire () print ' threadfuction-%d '%arg lock.release () if __name__ = = ' __main__ ': lock = Threading. Lock () threading. Thread (target = threadfunction, args= (1,)). Start (); Threading. Thread (target = Threadfunction, args= (2,)). Start ();
3. Condition variables
The condition variable is always used with the mutex, the conditional variable in threading is bound by default to a rlock, or it can be passed in a defined lock when the condition variable is initialized.
The available functions are as follows
Threading. Condition ([lock]) assigns a condition variable acquire (*args) condition variable lock release () condition variable to unlock wait ([timeout]) waiting to wake up, Timeout indicates timeout notify (n=1) wake up to n waiting Threads Notifyall (), Notify_all () wake up all waiting threads The following example uses a conditional variable to control two threads alternately running num = 0def Threadfunction (ARG): global num while num <: Cond.acquire () while num% 2! = arg: cond.wait () print ' Thread%d-%d '% (ARG, num) num + = 1 cond.notify () cond.release () if __name__ = = ' __main__ ': cond = Threading. Condition () threading. Thread (target = threadfunction, args= (0,)). Start (); Threading. Thread (target = threadfunction, args= (1,)). Start ();
The output is as follows
Thread 0-0thread 1-1thread 0-2thread 1-3thread 0-4thread 1-5thread 0-6thread 1-7thread 0-8thread 1-9th Read 0-10
In fact, the above program is problematic, we want to print the 0~9, but actually 10 is also printed out, the reason is very simple, because two threads alternate printing, so that num in a thread may add 2, resulting in 10 is printed out, so you must check again before printing.
It is believed that this article has some reference value to the Python program design of everyone.