python - multithreading, that's it

Posted by cubik on Tue, 18 Jan 2022 06:50:27 +0100

preface:

Before talking about threads, pull the process.

What is a process?

The program can not run alone. Only when the program is loaded into memory, the system can allocate resources for it to run, and this executed program is called a process.


The difference between procedures and processes lies in:

  • Program: it is a collection of instructions, which is the static description text of process operation;
  • Process: it is an execution activity of a program and belongs to a dynamic concept.

In multiprogramming, we allow multiple programs to be loaded into memory at the same time, which can be executed concurrently under the scheduling of the operating system. This is such a design, which greatly improves the utilization of CPU. The emergence of process makes each user feel that they have their own CPU. Therefore, the process is proposed to realize multi-channel programming on the CPU.


Why thread when there is a process?

Process has many advantages. It provides multi-channel programming, which makes us feel that each of us has our own CPU and other resources, which can improve the utilization of the computer.

However, the process is flawed:

The process can only do one thing at a time. If you want to do two or more things at the same time, the process can't do anything.

If a process is blocked during execution, such as waiting for input, the whole process will hang. Even if some work in the process does not depend on the input data, it will not be executed.

An operating system is compared to a factory. Each workshop is equivalent to a process. A workshop is composed of multiple employees who can produce in parallel. At this time, the efficiency of the workshop will rise. Each worker is a thread.

What is a thread?

Thread is the smallest unit that the operating system can schedule operations.

It is included in the process and is the actual operation unit in the process. A thread refers to a single sequential control flow in a process. Multiple threads can be concurrent in a process, and each thread executes different tasks in parallel.

Difference between process and thread:

  • Process is an executing program, which is the basic unit of resource allocation, and thread is the basic unit of CPU scheduling.
  • Processes are independent of each other, and resources cannot be shared between processes. A process has at least one thread, and each thread of the same process shares the resources (register, stack, context) of the whole process.
  • Thread creation and switching costs are less than processes.


Single thread

Let's look at the single threaded mode first

# coding=utf-8
from time import ctime, sleep  # ctime get current time

def dinner(func):
    for i in range(2):
        print("I'm having a meal: {}, Time: {}" .format(func, ctime()))
        sleep(1)  # Sleep for 1 s

def drink(func):
    for i in range(2):
        print("I'm drinking: {}, Time: {}" .format(func, ctime()))
        sleep(3)

if __name__ == '__main__':
    dinner("Pig feet rice")
    drink("Moutai")
    print("all over {}" .format(ctime()))

Define two functions, one for eating and one for drinking.

Look at the results first:

I'm having a meal: Pig feet rice, Time: Sat Jan 15 15:45:28 2022
I'm having a meal: Pig feet rice, Time: Sat Jan 15 15:45:29 2022
I'm drinking: Moutai, Time: Sat Jan 15 15:45:30 2022
I'm drinking: Moutai, Time: Sat Jan 15 15:45:33 2022
all over Sat Jan 15 15:45:36 2022

It starts at 15:45:28 and ends at 15:45:36, taking a total of 8 s
Now the program is a single thread mode, eat two pig feet rice, dry two Maotai, and execute in sequence.



Multithreading

Introduction to python multithreading official website:
https://docs.python.org/zh-cn/3.7/library/threading.html

Next, modify the following code to realize watching movies while eating pig's feet.

# coding=utf-8
import threading
from time import ctime, sleep  # ctime get current time

def dinner(func):
    for i in range(2):
        print("I'm having a meal: {}, Time: {}" .format(func, ctime()))
        sleep(1)  # Sleep for 1 s

def movie(func):
    for i in range(2):
        print("I'm watching movies: {}, Time: {}" .format(func, ctime()))
        sleep(3)

threads = []  # Create an empty array
# Using threading Thread() method, target: call dinner method, args: pass parameters 
thread1 = threading.Thread(target=dinner, args=("Pig feet rice",))
# Append the created thread thread1 to threads
threads.append(thread1)
print()  # Line feed
thread2 = threading.Thread(target=movie, args=("Forrest Gump",))
threads.append(thread2)

if __name__ == '__main__':
    # The for loop traverses the threads array
    for t in threads:
        t.setDaemon(True)
        # Start thread activity
        t.start()
    print()
    print("all over {}" .format(ctime()))

setDaemon()

setDaemon(True) declares a thread as a daemon thread, which must be set before the start() method call. If it is not set as a daemon thread, the program will be suspended indefinitely.

After the child thread starts, the parent thread also continues to execute. When the parent thread finishes executing the last statement
After print ("all over {}". Format (ctime())), you exit without waiting for the child thread, and the child thread ends at the same time.

Operation results of the above code:

I'm having a meal: Pig feet rice, Time: Sat Jan 15 16:18:29 2022
I'm watching movies: Forrest Gump, Time: Sat Jan 15 16:18:29 2022

all over Sat Jan 15 16:18:29 2022

According to the results, the child thread (diner and movie) and the main thread print ("all over {}". Format (ctime())) are started at the same time.

After setting the daemon thread, when the main thread ends, the child thread will also end immediately and will no longer execute.

The main thread waits for the child thread to end

In order to make the main thread end after the execution of the daemon thread (child thread), we can use the join method to make the main thread wait for the execution of the child thread.

for t in threads:
    t.join()

The position of the join() method is outside the for loop. After the two sub threads are finished, the main process can be executed.

# coding=utf-8
import threading
from time import ctime, sleep  # ctime get current time

def dinner(func):
    for i in range(2):
        print("I'm having a meal: {}, Time: {}" .format(func, ctime()))
        sleep(1)  # Sleep for 1 s

def movie(func):
    for i in range(2):
        print("I'm watching movies: {}, Time: {}" .format(func, ctime()))
        sleep(3)

threads = []
thread1 = threading.Thread(target=dinner, args=("Pig feet rice",))
threads.append(thread1)
print()  # Line feed
thread2 = threading.Thread(target=movie, args=("Forrest Gump",))
threads.append(thread2)

if __name__ == '__main__':
    for t in threads:
        t.setDaemon(True)
        t.start()
    for t in threads:
        t.join()
    print()
    print("end:  {}" .format(ctime()))

Look at the results first:

I'm having a meal: Pig feet rice, Time: Sat Jan 15 17:56:59 2022
I'm watching movies: Forrest Gump, Time: Sat Jan 15 17:56:59 2022
I'm having a meal: Pig feet rice, Time: Sat Jan 15 17:57:00 2022
I'm watching movies: Forrest Gump, Time: Sat Jan 15 17:57:02 2022

end:  Sat Jan 15 17:57:05 2022

The sub threads diner and movie start at the same time, starting at 17:56:59 until the main process is called at 17:57:05,
The total time is 6 s. It takes 8 s for single thread and 2 s for multi thread.

Therefore, it can be seen that multithreading will be faster.

Topics: Python