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/python 2 #-*-Coding:utf-8-* 3 author = ' Zni.feng ' 4 import sys 5 reload (SYS) 6 sys.setdefaultencoding ( ' Utf-8 ') 7 8 import threading, Time 9 def test (index): Print time.strftime ('%y-%m-%d%h:%m:%s ', Time.localtime (ti Me.time ())) [print ' thread%s starts. '% Threading.current_thread (). NAME13 print ' The index is%d '% index14 Time.sleep (3) Print time.strftime ('%y-%m-%d%h:%m:%s ', Time.localtime (Time.time ())) print ' thread%s ends. ' Hreading.current_thread (). name17 if Name = = "Main": Print Time.strftime ('%y-%m-%d%h:%m:%s ', Time.localtime (time.t IME ())) [print ' thread%s starts. '% Threading.current_thread (). name21 #创建线程22 My_thread = Threading. Thread (target = Test, args= (1,), name= ' Zni_feng_thread ') #等待2s24 time.sleep (2) #启动线程26 My_thread.sta RT () #等待线程结束28 my_thread.join () print time.strftime ('%y-%m-%d%h:%m:%s ', Time.localtime (Time.time ())) 30 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/python 2 #-*-Coding:utf-8-* 3 author = ' Zni.feng ' 4 import sys 5 reload (SYS) 6 Sys.setdefaultencodin G (' Utf-8 ') 7 import Threading 8 9 class account:10 def init (self): one self.balance = 012 def add (self): + for I in range (0,100000): self.balance + =, def delete (self): + for i in range (0,100000): 19
self.balance-=1 If Name = = "Main": Account = Account () #创建线程24 thread_add = Threading. Thread (Target=account.add, name= ' Add ') Thread_delete = Threading. Thread (target=account.delete, name= ' delete ') #启动线程28 thread_add.start () Thread_ Delete.start () #等待线程结束32 thread_add.join () thread_delete.join ( ) 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/python 2 #-*-Coding:utf-8-* 3 author = ' Zni.feng ' 4 import sys 5 reload (SYS) 6 sys.setdefaultencoding ( ' Utf-8 ') 7 Import Threading 8 9 class Account:10 def init (self): one self.balance = 012 def add (self, lo CK): #获得锁15 lock.acquire () for I in Range (0,100000): Self.balance + = 118 #释放锁19 lock.release () def delete (self, lock): #获得锁23 Lock.acquire () Range (0,100000): Self.balance-=1 #释放锁27 lock.release (), if name = = "Main": 31 Account = account () + lock = Threading. Lock () #创建线程34 Thread_add = Threading. Thread (Target=account.add, args= (lock,), name= ' Add '), Thread_delete = Threading. Thread (Target=account.delete, args= (lock,), name= ' delete ') Notoginseng #启动线程38 thread_add.start () thread_delete.s Tart () #等待线程结束42 thread_add.join () Thread_delete.join () 44 45print ' 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]
"Recommended"
1. Multi-process and multithreaded instances in Python (i)
2. Is it recommended to use multiple processes instead of multithreading in Python? Reasons to share recommended multi-process
3. Is Python multi-process fast or multithreaded?
4. Detailed description of Python processes, threads, and schedules
5. Python thread pool/process pool for concurrent programming