This paper describes the usage of multithreading in Python in detail, which is widely used in Python programming. Share for everyone to use for reference. The specific analysis is as follows:
Python operations on multithreading can be implemented using thread and threading modules, where the thread module has been renamed _thread in Py3 and is no longer recommended for use. and the threading module is on the thread of encapsulation, is recommended to use multithreaded module, this article is mainly based on the threading module to introduce. The thread module may not exist in some versions, using dump_threading instead of the threading module.
One, thread creation
Each thread in the threading module is a thread object, and there are two ways to create one: the function is passed to the thread object, the other is inherited from thread, and then the Run method is rewritten (is it like Java).
The following two methods are used to create a separate thread and execute the
Import Random, threading
def 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 results are as follows: You can see that two threads are printing alternately. As for blank lines and multiple outputs, because the print for PY is not thread-safe, after the current thread's print has printed part of the content, it is preempted by the print in the other thread before it is printed, and then prints the rest before the line wraps.
ThreadFuction-0
ThreadFuction-1
ThreadFuction-2
ThreadClass-0
ThreadFuction-3
ThreadClass- 1
ThreadFuction-4
ThreadClass-2
ThreadClass-3
threadclass-4threadfuction-5
ThreadClass-5
ThreadClass-6
ThreadClass-7
ThreadClass-8
threadfuction-6threadclass-9
ThreadFuction-7
threadfuction-8
threadfuction-9
The constructor for the thread class is defined as follows
Class Threading. Thread (Group=none, Target=none, Name=none, args= (), kwargs={})
Group: For Threadgroup extended use, generally no use
Target: The name of the task function of the new thread
Name: Thread name, which is generally useless
Args:tuple parameters
Kwargs:dictionary parameters
The member variables and functions of the thread class are as follows
Start () starts a thread
The run () thread executor, which is what is commonly overridden
Join ([timeout]) waits for thread to end
Name Thread Name
Ident thread ID
Daemon whether to guard threads
Whether the isAlive (), is_alive () thread survives
Get&set method for GetName (), SetName () name
Get&set method of Isdaemon (), Setdaemon () daemon
The daemon thread here is not a concept with the daemon in Linux. This means that when all daemons exit the master program, they will exit, even if the thread task does not end, as long as it is not a daemon, it exits along with the main program. The daemon definition in Linux is exactly the opposite, and the daemon is out of the parent process and will not exit as the parent process ends.
Second, thread synchronization
thread synchronization is a core problem in multithreading, threading module has good support for thread synchronization, including thread specific data, semaphore, mutex, condition variable, etc.
1. Thread-specific data
In short, thread-specific data is the global variable that the thread holds alone, and modifications between them are not affected.
The local () method is used in the threading module to generate a thread-independent object, for example, where sleep (1) is designed to ensure that the child thread runs before running the next statement.
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
<thread (Thread-1, started 36208) > 3
<_mainthread (Mainthread, started 35888) > 1
As you can see on the output, the modification of data.x in Thread-1 does not affect the value of data.x in the main thread.
2. Mutual exclusion Lock
Two types of locks are defined in threading: Threading. Lock and Threading.rlock. The difference is that the latter is a reentrant lock, which means that locking the same lock without deadlock in one thread is the same as the concept of pthread_mutex_recursive in POSIX, which is the recursive lock.
The API for mutexes is simple, with only three functions ———— assign locks, lock them, unlock them.
Threading. Lock () assign a mutex
Acquire ([blocking=1]) is locked (blocking or non-blocking, which is equivalent to Try_lock when non-blocking) and is locked by another thread by returning false. )
Release () Unlock
The following is an example to illustrate the use of mutexes. In the previous example, multithreaded print created a messy output, using a mutex to guarantee that there must be only one output per line.
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 variable
A condition variable is always used with a mutex, and the condition variable in the threading is bound by default to a rlock, or it can be passed in a lock of its own definition when the condition variable is initialized.
The functions available are as follows
Threading. Condition ([lock]) assigns a condition variable
acquire (*ARGS) conditional variable lock release
() conditional variable unlocking
wait ([timeout]) waiting for Wake, Timeout indicates that the timeout
notify (n=1) wakes up the maximum n waiting threads
notifyall (), Notify_all () wakes all waiting threads
The following example uses a condition variable to control two threads running alternately
num = 0
def 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 ();
Output is as follows
Thread 0-0
thread 1-1 thread
0-2 thread
1-3
thread 0-4 thread 1-5 thread 0-6
thread 1-7 thread
0-8 thread
1-9 thread
0-10
In fact, this program is problematic, we wanted to print 0~9, but in fact 10 was also printed, for the simple reason that two threads alternately print so that NUM can add 2 to one thread, which causes 10 to be printed, so you must check again before printing.
It is believed that this article has certain reference value to everyone's Python programming.