In the previous chapter, we learned some basic methods of Python multi-process programming: Using the process, Pool, Queue, Lock, pipe, and other classes provided by the cross-platform multi-process module multiprocessing, to achieve child process creation, Process pools (batch creation of child processes and managing the maximum number of child processes) and interprocess communication. This chapter learns the multithreaded programming approach under Python.
First, threading
A thread is the smallest unit on which the operating system performs tasks. The threading module is available in the Python standard library and provides easy support for multithreaded programming.
Here is the code that implements multithreading using threading:
1 #!/usr/bin/python2 #-*-coding:utf-8-*3 __author__='Zni.feng'4 ImportSYS5 Reload (SYS)6Sys.setdefaultencoding ('Utf-8')7 8 Importthreading, time9 Ten defTest (Index): One PrintTime.strftime ('%y-%m-%d%h:%m:%s', Time.localtime (Time.time ())) A Print 'thread%s starts.'%Threading.current_thread (). Name - Print 'The index is%d'%Index -Time.sleep (3) the PrintTime.strftime ('%y-%m-%d%h:%m:%s', Time.localtime (Time.time ())) - Print 'thread%s ends.'%Threading.current_thread (). Name - - if __name__=="__main__": + PrintTime.strftime ('%y-%m-%d%h:%m:%s', Time.localtime (Time.time ())) - Print 'thread%s starts.'%Threading.current_thread (). Name + #Creating Threads AMy_thread = Threading. Thread (target = Test, args= (1,), name='Zni_feng_thread') at #wait 2s -Time.sleep (2) - #Start Thread - My_thread.start () - #wait for thread to end - My_thread.join () in PrintTime.strftime ('%y-%m-%d%h:%m:%s', Time.localtime (Time.time ())) - Print 'thread%s ends.'% Threading.current_thread (). Name
The output is:
2017-01-12 22:06:32thread mainthread starts.2017-01-12 22:06:34thread zni_feng_thread starts.the index is 12017-01-12 22 : 06:37thread zni_feng_thread ends.2017-01-12 22:06:37thread mainthread ends. [Finished in 5.1s]
where the Current_thread () function of the threading module returns an instance of the current thread.
Second, Lock
The biggest difference between multi-process and multi-threading is that in many processes, the same variable, each one copy exists in each process, does not affect each other. In multi-threading, all variables are shared by all threads, so any shared variable can be modified by any thread. So the biggest danger of sharing data between threads is that multiple threads change a variable at the same time. To solve this problem, we can use the lock class of the threading module to lock the shared variable.
Let's take a look at the example of using multithreading to write the same shared variable without locking:
1 #!/usr/bin/python2 #-*-coding:utf-8-*3 __author__='Zni.feng'4 ImportSYS5 Reload (SYS)6Sys.setdefaultencoding ('Utf-8')7 ImportThreading8 9 classAccount :Ten def __init__(self): OneSelf.balance =0 A - defAdd (self): - forIinchRange (0,100000): theSelf.balance + = 1 - - defDelete (self): - forIinchRange (0,100000): +Self.balance-=1 - + if __name__=="__main__": AAccount =Account () at #Creating Threads -Thread_add = Threading. Thread (Target=account.add, name='ADD') -Thread_delete = Threading. Thread (Target=account.delete, name='Delete') - - #Start Thread - Thread_add.start () in Thread_delete.start () - to #wait for thread to end + Thread_add.join () - Thread_delete.join () the * Print 'The final balance is:'+ STR (account.balance)
The result of the operation is:
The final balance is: -51713[finished in 0.1s]
It can be found that the end result will be different for each run, and it will not be 0. This is because a conflict occurs when different threads modify the same variable at the same time, and some intermediate variables are not used in order.
Now we lock the program with Lock:
1 #!/usr/bin/python2 #-*-coding:utf-8-*3 __author__='Zni.feng'4 ImportSYS5 Reload (SYS)6Sys.setdefaultencoding ('Utf-8')7 ImportThreading8 9 classAccount :Ten def __init__(self): OneSelf.balance =0 A - defAdd (self, lock): - Lock.acquire () the forIinchRange (0,100000): -Self.balance + = 1 - lock.release () - + defDelete (self, lock): - Lock.acquire () + forIinchRange (0,100000): ASelf.balance-=1 at lock.release () - - - if __name__=="__main__": -Account =Account () -Lock =Threading. Lock () in #Creating Threads -Thread_add = Threading. Thread (Target=account.add, args= (lock,), name='ADD') toThread_delete = Threading. Thread (Target=account.delete, args= (lock,), name='Delete') + - #Start Thread the Thread_add.start () * Thread_delete.start () $ Panax Notoginseng #wait for thread to end - Thread_add.join () the Thread_delete.join () + A Print 'The final balance is:'+ STR (account.balance)
It can be found that the balance result is 0 regardless of how many times it is executed. If you print out the results of each balance calculation, you will also find that when one thread starts executing, the other thread must wait until the previous thread finishes executing (exactly lock.release () executes) before starting execution.
The final balance is:0[finished in 0.1s]
Multi-process and multithreading in Python (ii)