This is the 17th day of my participation in the August More text Challenge. For details, see: August More Text Challenge

thread

A Thread, sometimes referred to as a Lightweight Process (LWP), is the basic unit of an operating system for independent scheduling and dispatch, and is essentially a set of instructions. A standard thread by thread id, the current instruction pointer (PC), register set and stack, it is an entity, in the process of the thread itself does not have the system resources, with only a little in operation of essential resources (such as the program counter, a register, stack), but it can be to belong to a Shared other threads of a process possesses all the resources. Threads cannot execute independently and must be dependent on processes.

multithreading

Multithreading is to use multiple threads to execute tasks at the same time, realize the parallel execution of tasks, so as to improve the efficiency of the program.

Imagine if within a single thread to perform multiple tasks (such as sending the requests, etc.), if the task in front of the more time-consuming, and the task need to wait for the finished tasks to perform in front of, this will affect the task execution efficiency, you can use multiple threads to perform these tasks, the task can be done at the same time, it will greatly improve the efficiency of execution.

Python multithreading

In Python, the threading module is provided to enable multi-process operations. This module is based on the lower-level module _Thread, which provides an easy-to-use high-level multithreading API.

Create a thread

Thread objects can be created using the Thread class in the Threading module. Thread(group, target, name, daemon)

  • Group: Defaults to None (this parameter is reserved for later implementation of ThreadGroup)
  • Target: The callable object called in the run method, which is the task to be executed by the thread
  • Name: Indicates the name of the Thread. This parameter is optional. The default value is “thread-n”
  • Args: Arguments passed to the function specified by target, in tuples
  • Kwargs: Passes named arguments to the function specified by target
  • Daemon: Defaults to None and explicitly sets whether the thread is in daemon mode. If None, the thread inherits the daemon mode properties of the current thread

Thread common methods

  • Start () : Starts the thread and calls the run() method in that thread
  • Run () : The method that runs when the thread starts, and it is this method that calls the function specified by target
  • Join (timeout=None) : Make the current caller thread (typically the main thread) wait until it terminates. Timeout is an optional timeout
  • Is_alive () : returns whether the current thread is alive
import threading
import time


def work(i) :
    print("Child thread '{}'work is running......".format(threading.current_thread().name))
    time.sleep(i)
    print("Child thread '{}' run ends......".format(threading.current_thread().name))


if __name__ == '__main__':
    print("Main thread {} starts".format(threading.current_thread().name))
    Get the name of the thread
    threads = []
    for i in range(5):
        t = threading.Thread(target=work, args=(i,))
    # Start thread
        threads.append(t)
        t.start()
    for t in threads:
        t.join()
    print("End of main thread")
Copy the code

The execution result is:

The function of using t.daemon () in the above code is to make the main thread wait for all subthreads to finish. If you want to set daemons (when the main thread ends, the subthreads also end, whether or not the task completes), you can use t.daemon = True.

GIL lock

The Global Interpreter Lock is the name of the Interpreter Lock. This Lock is designed to ensure that the same data cannot be modified by multiple threads at the same time. Each thread needs to acquire the GIL before executing a task, so that only one thread can execute the task at a time. That is, only one thread is running in the interpreter at any one time, so multithreading in Python is false multithreading, not true multithreading. If there are more than one thread in the program executing a task, the interpreter will take turns executing it, but it will switch quickly and frequently, giving the illusion that multiple threads are executing “simultaneously.”

The thread pool

As mentioned in the previous article, processes have a process pool mechanism, and threads have thread pools as well. A thread pool can create a custom number of idle threads when the program starts. Whenever the program submits a task to the thread pool, the pool will start one idle thread to execute it. When the task is finished, the thread does not die, but returns to the pool again and becomes idle, waiting for the next task to execute.

Dummy also has a Pool object in multiprocessing. It is an encapsulation of threads and is used very similar to multiprocessing’s Pool. Dummy is a thread pool module copied by the multiprocessing process pool module. Again, the thread pool is GIL restricted.

The usage mode is the same as that of multiprocessing.Pool. For details, see Python Process Pool.

from multiprocessing.dummy import Pool
import time


def work(i) :
    print("Work '{}' executing......".format(i))
    time.sleep(2)
    print("Work '{}' completed......".format(i))


if __name__ == '__main__':
    # Create thread pool
    # Pool(5) creates a thread Pool of 5 threads
    pool = Pool(5)
    for i in range(10):

        pool.apply_async(work, (i, ))
    pool.close()
    pool.join()
Copy the code

conclusion

Because multithreading in Python is limited by THE GIL lock, it cannot take advantage of the multi-core feature of the machine. It can only use single-core, which is false multithreading. However, it is not useless. This will waste waiting for this period of time, and can open multiple threads in the thread A waiting, automatically switch to the thread B, can reduce the unnecessary waste of time, which can improve the efficiency of the program, but may not be the best choice, for handling IO intensive tasks, better options in Python coroutines, in subsequent articles will be introduced.

Finally, I would like to thank my girlfriend for her tolerance, understanding and support in work and life.