Threads of (detailed) tutorials on processes and threads in Python

Threading:

In a process, to do many things at the same time, you need to run multiple subtasks at the same time. We call these subtasks in the process multithreading

For example, to play LOL, it is only a process, but it can be controlled by mouse and keyboard. So many subtasks are operated by threads

  • Threads are often called lightweight processes. Threads are multitasks executed concurrently in shared memory space, and each thread shares the resources of a process

  • Thread is the smallest execution unit, and the process is composed of at least one thread. How to schedule the process and thread is completely determined by the operating system. The program itself cannot decide when to execute and how long to execute

Modular:

1. Thread module
Low level module, low level is close to the bottom, not very low
2.threading module
Advanced module, encapsulating "thread"

Start a thread

import threading
import time

def run():
    print("Sub thread(%s)start"% (threading.current_thread().name))

    # Implement the function of sub thread
    print("Mobile mouse")
    time.sleep(2)

    print("Sub thread(%s)End" % (threading.current_thread().name))

if __name__ == "__main__":
    # Any process will start a thread by default and become the main thread. The main thread can start a new sub thread
    # Current ou thread(): returns an instance of the current thread
    print("Main thread(%s)start-up" % (threading.current_thread().name))

    # Create child thread                      
    t = threading.Thread(target=run)
    # Let child threads work
    t.start()

    print("Main thread(%s)End" % (threading.current_thread().name))

Operation result:

We found that we didn't define the names of the main thread and the sub thread. This is the default. If we don't name the sub thread, it will be Thread-1 and thread-2 by default
Now we can name the sub thread

t = threading.Thread(target=run,  name="runThread")

Operation result:

We see that the main thread does not wait for the sub thread to finish, but the sub thread has no effect

  • In Windows system, after the main thread ends, it is not destroyed in memory, so the sub thread can also run
  • But in Linux system, after the main thread ends, it will be destroyed in memory immediately, so the sub thread cannot run
  • The two are very different

Now let's let the main thread wait for the child thread to finish

t.start()
# Wait for child thread to end
t.join()
print("Main thread(%s)End" % (threading.current_thread().name))

Operation result:

The difference between thread and process

The biggest difference between multithreading and multiprocessing is that

  • In multiple processes, one copy of the same variable exists in each process, which does not affect each other
  • In multithreading, all variables are shared by all threads, so any variable can be modified by any thread. Therefore, the biggest danger of sharing data between threads is that multiple threads modify one variable at the same time, which is easy to change the content disorderly

Sharing data between threads

import threading
import time
num = 10

def run(n):

    # Implement the function of sub thread
    global num
    for i in range(1000000):
        num += n
        num -= n

if __name__ == "__main__":
    t1 = threading.Thread(target=run, args=(3,))
    t2 = threading.Thread(target=run, args=(5,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print("num = %s" % (num))

Operation result:

num = 18

Theoretically, the result should be num = 10, but why is it different?
The reason is very simple. Two sub threads are running at the same time. It may be because of the fast and slow running speed that num += n, or num -= n execution order is not the same, resulting in the calculation deviation. Therefore, sharing data between threads is a very dangerous thing

Thread lock

Thread lock: ensures that there is only one thread working in this code from beginning to end

  • The concurrent execution of multithreading is prevented. In fact, some code containing lock can only be executed in single thread mode, so the efficiency is greatly reduced
  • Other code without lock is still multithreaded, only the lock position is single thread, so it is faster than single thread
  • Because there can be multiple locks, different threads hold different locks, and try to acquire other locks, which may cause deadlock and multiple threads hang. Termination can only be enforced by the operating system

Example:

import threading
num = 10

"""Instantiate lock object"""
lock = threading.Lock()

def run(n):

    """Implement the function of sub thread"""
    global num
    for i in range(1000000):
        """lock
        //When the thread reaches this point, it will be locked, and then thread 2 will not be able to access it
        //When a thread finishes accessing, it releases the lock, which is equivalent to unlocking. Then thread 2 can access ""“
        """Lock up"""
        lock.acquire()
        """The program may go wrong, so we need to try Once"""
        try:
            num += n
            num -= n
        """Make sure to release the lock after modification
        //No matter what happens on the top, we must release the lock on the bottom“
        finally:
            lock.release()

        """It has the same function as the above code, with lock Can lock and unlock automatically"""
        """Only one of the two locks can be selected at a time"""
        with lock:
            num += n
            num -= n
        """This way is safer than the above way, and the possibility of deadlock is greatly reduced"""

if __name__ == "__main__":
    t1 = threading.Thread(target=run, args=(3,))
    t2 = threading.Thread(target=run, args=(5,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print("num = %s" % (num))

Operation result:

num = 10

In this way, we will not make calculation errors due to two threads

ThreadLocal

Each thread has its own storage space. It can read and write ThreadLocal objects, but it does not affect each other

import threading

num = 0
"""Create a global ThreadLocal object
//Each thread has its own storage space
//Each thread can read and write to the ThreadLocal object, but does not affect each other“

"""instantiation ThreadLocal object"""
local = threading.local()

def func(n):
    """Every thread has local.x, Is the thread's local variable"""
    local.x = num
    for i in range(1000000):
        run(local.x, n)
    print("%s--%s" % (threading.current_thread().name, local.x))


def run(x, n):
    x += n
    x -= n

if __name__ == "__main__":
    t1 = threading.Thread(target=func, args=(3,))
    t2 = threading.Thread(target=func, args=(5,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print("num = %s" % (num))

"""Function: bind a database link for each thread, or user identity information, or HTTP request
//All the processing functions called by such a thread can easily access these resources“

Operation result:

Thread-1--0
Thread-2--0
num = 0

It won't have an impact. It's good

If you have any mistakes or questions, please send me a private message. Thank you for watching

Published 20 original articles, won praise 22, visited 3267
Private letter follow

Keywords: Mobile Windows Linux Database

Added by Strings on Thu, 27 Feb 2020 12:05:10 +0200