python third party Library -- threading module

Thread introduction

  1. Thread is a processing task unit lower than the process. Sometimes it is also called lightweight process. It is the smallest unit of program execution flow. It can be said that multiple threads can be created in a process to process multiple tasks
  2. The components of a thread can be divided into thread ID, current system instruction pointer, register set and stack combination.
  3. Thread is an entity in a process and the basic unit independently scheduled and dispatched by the system. Thread does not have private system resources. There are one or more processes in the operating system. Each process has its own exclusive CPU resources. Different processes cannot share resources. However, if it is necessary to share CPU resources now, it can be realized through thread technology
  4. Threads are more lightweight control units than processes, and the cost of creating and destroying threads is less. Using threads can improve the processing performance of processes
  5. It is called multithreading technology to run multiple threads to complete different work at the same time in a single program

Modern processors are multi-core, multi-threaded execution programs, which seem to be carried out at the same time, but in fact, the CPU quickly switches between multiple threads

The threading module implements multithreading

Use the Thread class
Use format:

t=threading.Thread(target=None,name=None,args=())
parameterdescribe
targetA function or method called when a thread starts
nameThread name
argsThe function requires an passed in parameter (in tuple form)

Main methods of Thread object

methodbrief introduction
run()Method used to represent thread activity
start()Start thread
join()Wait until the thread terminates
isAlive()Determine whether the thread is active
getName()Returns the thread name
setName()Set thread name

Functional thread creation

When creating a Thread, you only need to pass in an execution function and function parameters. The following example uses the Thread class to generate two sub threads and wait for them to end

import threading
import time,os,random,math

def printnum(num):
    for i in range(num):
        print(f'{threading.current_thread().getName()},{i}')
        time.sleep(1)
if __name__=='__main__':
    t1=threading.Thread(target=printnum,args=(2,),name='thread1')
    t2=threading.Thread(target=printnum,args=(3,),name='thread2')
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(f'{threading.current_thread().getName()}Thread end')

Operation results

Create thread class

Directly create a subclass of Thread to create a Thread object to realize multithreading

import threading,time
class mythread(threading.Thread):
    def __init__(self,name,num):
        threading.Thread.__init__(self)
        self.name=name
        self.num=num
    def run(self):		# The run() method is called automatically after the thread starts
        for i in range(self.num):
            print((f'{threading.current_thread().getName()},{i}'))
            time.sleep(1)
if __name__=='__main__':
    t1=mythread('thread1',3)
    t2=mythread('thread2',2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print((f'{threading.current_thread().getName()}Thread end'))

Operation results

Two functions in the threading module get the active thread information

functiondescribe
active_count()Gets the number of currently active threads
encumerate()Get the active thread information and return a list sequence

Daemon thread

The main thread needs to wait for the execution of the child thread before continuing. If the child thread does not use the join() function, the main thread and the child thread run together and there is no dependency between them
Use format: thread object. setDaemon(True)
In multithreaded programming, if the child thread is set as the guardian thread of the main thread, it will be destroyed after waiting for the main thread to run. At this time, the premise of the guardian thread running is that the resident thread must exist

import threading
import time
def run(taskname):
    print(f'task-{taskname}')
    time.sleep(2)
    print(f'task-{taskname}completion of enforcement')
if __name__=='__main__':
    for i in range(3):
        thread=threading.Thread(target=run,args=(f'{i}',))
        thread.setDaemon(True)
        thread.start()
    print(f'Thread end:{threading.current_thread().getName()},The current number of threads is:{threading.active_count()}')    

Operation results

You can see that after the main thread is executed, the program exits without waiting for the daemon thread to execute

Thread termination

The threading module does not provide a thread termination method, nor does it support directly stopping threads. Threads created through Thread() are independent of each other. If child threads are started in the main thread, they are also independent threads
Thread termination method
If you want to forcibly terminate the child thread while terminating the main thread, the simplest method is to set the child thread as the guardian thread, which is a way to stop the thread. There are other methods to stop the child thread

  1. Generate the thread object, put the complex business in the loop, set a stop flag bit for the thread object, and exit the loop once the flag bit reaches the predetermined value, so that the thread can be stopped
import threading
import time

class testthread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self._running=True		# Set thread flag bit
    def terminate(self):
        self._running=False
    def run(self):
        count=1
        threadname=threading.current_thread().getName()
        while self._running:
            print(f'Thread Name:{threadname},Times:{count}')
            count+=1
            time.sleep(1)
if __name__=='__main__':
    t1=testthread()
    t1.start()
    time.sleep(3)		# Wait for three seconds, and the number of periods is increased by 3
    t1.terminate()		# Modify the value of the flag bit and stop the child thread
    print('Main thread end')


2. Call the ctypes module to report an exception in the child thread and make the child thread exit

Multithreaded locking mechanism

The problem of lock mechanism is solved
When multiple threads modify global variables at the same time, there will be data security problems. In short, it is possible that multiple threads modify data successively, resulting in inconsistent data, also known as "dirty data"

Case 1: two threads modify one data at the same time

import threading

num=10
def change_num(m,counter):
    global num
    for i in range(counter):
        num+=m
        num-=m
        if num!=10:		# Create a warning statement. If the statement is executed, it indicates
            print(f'num The value of is:{num}')
            break
if __name__=='__main__':
    t1=threading.Thread(target=change_num,args=(10,500000),name='Thread 1')
    t2=threading.Thread(target=change_num,args=(10,500000),name='Thread 2')
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(f'Thread end:{threading.current_thread().getName()}')

Operation results

Through the running results, we can find that change_ The num() function should be added and then subtracted to ensure that the value of num is always 10, but the result is not the same. In fact, the scheduling of threads is determined by the system. Two threads are started at the same time to execute alternately. As long as the number of times is enough, the result of num may not be 10

Introduction to mutex
For thread safety, mutexes need to be used. When a thread wants to modify a data resource, it first locks it. At this time, the state of the resource is "locked", and other threads cannot change it. Other threads cannot lock the resource again until the thread releases the resource,
Meaning of mutex
Mutex ensures that only one thread can write at a time, thus ensuring the correctness of data
Core code of locking mechanism

# Create a lock object
lock1=threading.Lock()
# locking
lock1.acquire()
# release
lock1.release()

Case 2: two threads modify the same data (lock)

import threading

num=10
lock=threading.Loak()
def change_num(m,counter):
    global num
    for i in range(counter):
    	lock.acquire()		# Acquire lock
        num+=m
        num-=m
        lock.release()		# After the thread that obtains the lock runs out, it must release the lock, otherwise other threads will wait all the time and become dead threads
        if num!=10:		
            print(f'num The value of is:{num}')
            break
if __name__=='__main__':
    t1=threading.Thread(target=change_num,args=(10,500000),name='Thread 1')
    t2=threading.Thread(target=change_num,args=(10,500000),name='Thread 2')
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(f'Thread end:{threading.current_thread().getName()}')

Operation results

In case 2 above, we are in change_ A lock mechanism is added to the num () function so that when a process executes change_ When the num () function is used, the lock will be obtained, while other threads will wait until the lock is obtained. In this way, when the two threads modify the global variable num, there will be no conflict, ensuring the security of the data

Tags: Python

Posted on Sun, 07 Nov 2021 18:43:21 -0500 by olechka