Python USES threading to implement multithreading in detail

  • 2020-05-26 09:24:24
  • OfStack

multithreading

Multithreading is a good way to improve the efficiency of a program. Programs that should have been executed sequentially can now be executed in parallel. But multithreading doesn't make all applications more efficient. Two extremes in the process is' CPU intensive 'and' I/O intensive 'two kinds, multi-thread technology is applied to the latter, because when you go to read and write in the serial structure disk or network communication CPU is idle, after all the network several orders of magnitude slower than disk, disk is orders of magnitude slower than memory, memory is orders of magnitude slower than CPU again. Multithreading can be performed simultaneously. For example, your program needs to send N http packets (10 seconds), copy files from one location to another (20 seconds), and count the number of 'hello,world' strings in another file (4 seconds). Now it takes 34 seconds for 1. But because there is no correlation between these operations, they can be written as multithreaded programs that take almost 20 seconds to complete. This is for I/O intensive, not CPU intensive. For example, if my program has to compute 1,000 factorial (10 seconds), and I have to compute the sum of 100,000 (5 seconds), then even if the program is parallel, it will take 15 seconds or more. Since CPU is executed by rotation when CPU is used, IO intensive programs can be evaluated with CPU at the same time as IO, but CPU intensive programs can only execute thread 1 and thread 2 at the same time. So it takes 15 seconds, or even more, because CPU takes time to switch. It is CPU's job to solve the multithreading problem of CPU intensive program, such as Intel's hyper-threading technology, which can truly parallel two threads on the same core, so it is called 'dual-core 4 threads' or' 4-core 8 threads'. We won't talk about the details here, and I don't know.

Python cheating

With all the talk about the benefits of multithreading, Python doesn't really support multithreaded programming. In Python there's a thing called GIL, which in Chinese is the global interpreter, which controls Python so that Python can only run one thread at a time. It is equivalent to saying that the real multithreading is controlled by CPU, and the multithreading in Python is controlled by GIL. If you have an CPU intensive program written in C language and running on a 4 core processor, you can get up to 4 times the efficiency improvement if you use multithreading technology. However, if you write in Python, you will not get any improvement, or even slow down, because of the problem of thread switching. So Python multithreading is relatively more suitable for writing I/O intensive programs. Besides, the really efficient CPU intensive programs all use C/C++.

First multithreading

In Python, multithreaded library 1 USES thread and threading, thread is not recommended for beginners and 1 people, threading module is quite enough to use.

There is one procedure, as follows. Two cycles, sleep for 3 seconds and sleep for 5 seconds, and execute serially for 8 seconds.


#!/usr/bin/env python
# coding=utf-8
import time
def sleep_3():
 time.sleep(3)
def sleep_5():
 time.sleep(5)
if __name__ == '__main__':
 start_time = time.time()
 print 'start sleep 3'
 sleep_3()
 print 'start sleep 5'
 sleep_5()
 end_time = time.time()
 print str(end_time - start_time) + ' s'

The output looks like this


start sleep 3
start sleep 5
8.00100016594 s

We then modified it to make it a multithreaded program, although the changes were few lines long. First, threading's library was introduced, and then one was instantiated threading.Thread Object, pass 1 function into the constructor. Then call Thread's start method to start one thread. join() Method can wait for the thread to finish, as I use below, if I don't add the two code waiting for the thread to finish, then the output time statement will be executed directly, so that the time of 1 is not counted correctly.


#!/usr/bin/env python
# coding=utf-8
import time
import threading #  The introduction of threading
def sleep_3():
 time.sleep(3)
def sleep_5():
 time.sleep(5)
if __name__ == '__main__':
 start_time = time.time()
 print 'start sleep 3'
 thread_1 = threading.Thread(target=sleep_3)  #  instantiation 1 Thread object to make the thread execute this function 
 thread_1.start()  #  Start this thread 
 print 'start sleep 5'
 thread_2 = threading.Thread(target=sleep_5)  #  instantiation 1 Thread object to make the thread execute this function 
 thread_2.start()  #  Start this thread 
 thread_1.join()  #  Waiting for the thread_1 The end of the 
 thread_2.join()  #  Waiting for the thread_2 The end of the 
 end_time = time.time()
 print str(end_time - start_time) + ' s'

The result is this


start sleep 3
start sleep 5
5.00099992752 s

daemon daemon threads

Daemons should be important in our understanding, analogous to daemons in Linux. But in the threading.Thread But not in China.

If a thread is set to a daemon thread, it means that the thread is not important and does not need to wait for the thread to finish executing when the process exits. -- Python core programming version 3

By default, all threads in the Thread object are non-daemon threads. Here are two examples to illustrate the difference. This code executes without specifying the daemon property of my_thread, so it defaults to non-daemon, so the process waits for it to finish. And then you end up with 100 hello,world


#!/usr/bin/env python
# coding=utf-8
import threading
def hello_world():
 for i in range(100):
  print 'hello,world'
if __name__ == '__main__':
 my_thread = threading.Thread(target=hello_world)
 my_thread.start()

Here, my_thread is set as the daemon thread, so the process just exits without waiting for its end, so we can't see 100 hello,world only has a few. It even throws an exception to tell us that a thread is not finished.


#!/usr/bin/env python
# coding=utf-8
import threading
def hello_world():
 for i in range(100):
  print 'hello,world'
if __name__ == '__main__':
 my_thread = threading.Thread(target=hello_world)
 my_thread.daemon = True #  The flag bit is set True
 my_thread.start()

Pass a parameter

The previous code is to directly execute 1 piece of code, without passing the parameters, so how to pass the parameters? It's actually quite simple. threading.Thread(target=hello_world, args=('hello,', 'world')) That's it. args is followed by a tuple. If there are no parameters, you can not write them. If there are parameters, you can add them in the tuple in order.


#!/usr/bin/env python
# coding=utf-8
import threading
def hello_world(str_1, str_2):
 for i in range(10):
  print str_1 + str_2
if __name__ == '__main__':
 my_thread = threading.Thread(target=hello_world, args=('hello,', 'world')) #  You pass the parameters here 
 my_thread.start()

Let's do another multithreading

threading has three ways to create Thread objects, but 1 only USES two. One is to pass in a function, as described above by 0X02, and the other is inheritance threading.Thread . Here we've defined two classes ourselves, which we've overridden run() Method, which is called start() After the execution of the code, starting the thread is the same as before. The previous approach was more procedural, this one is more object-oriented.


#!/usr/bin/env python
# coding=utf-8
import threading
class MyThreadHello(threading.Thread):
 def run(self):
  for i in range(100):
   print 'hello'
class MyThreadWorld(threading.Thread):
 def run(self):
  for i in range(100):
   print 'world'
if __name__ == '__main__':
 thread_hello = MyThreadHello()
 thread_world = MyThreadWorld()
 thread_hello.start()
 thread_world.start()

conclusion

The above is the whole content of this article, I hope the content of this article to your study or work can bring 1 definite help, if you have questions you can leave a message to communicate.


Related articles: