It won’t. don’t say you play programming

Time:2021-12-9

Thread overview

Multithreading is similar to executing multiple different programs at the same time. Multithreading has the following advantages:

Using threads, you can put tasks in programs that occupy a long time in the background.

The user interface can be more attractive. For example, if the user clicks a button to trigger the processing of some events, a progress bar can pop up to display the processing progress

The program may run faster

In the implementation of some waiting tasks, such as user input, file reading and writing, network sending and receiving data, threads are more useful. In this case, we can release some precious resources, such as memory occupation and so on.

Threads are different from processes during execution. Each independent process has a program entry, sequential execution sequence and program exit. However, threads cannot be executed independently. They must be stored in the application, and the application provides multiple thread execution control.

Each thread has its own set of CPU registers, called the thread context, which reflects the state of the CPU register in which the thread last ran.

Instruction pointer and stack pointer registers are the two most important registers in the thread context. Threads always run in the process context. These addresses are used to mark the memory in the process address space of the thread.

Threads can be preempted (interrupted).

While other threads are running, threads can be temporarily suspended (also known as sleep) — this is the concession of threads.

Thread is a branch that executes program code during program running. Each running program has at least one thread

Create multithread: thread

Call start in the thread module_ new_ Thread() function to generate a new thread

thread.start_new_thread ( function, args[, kwargs] )

Function - thread function.

Args - the parameter passed to the thread function. It must be of type tuple.

Kwargs - optional parameter.

Python multithreading on

start()
import threading

import time

def task():

    time.sleep(1) 

     Print ("current thread:", threading. Current_thread(). Name)

if__name__ =='__main__':

    for_inrange(5):

         sub_thread = threading.Thread(target=task) 

         sub_thread.start()

Execution between threads is out of order

The main thread will wait for all child threads to end

The main thread will wait until all sub threads are finished. If necessary, you can set the guard main thread

Characteristics of multithreading (sharing global variables)

Threading. Currentthread(): returns the current thread variable.

Threading. Enumerate(): returns a list of running threads. Running refers to threads after starting and before ending, excluding threads before starting and after termination.

Threading. Activecount(): returns the number of running threads, which is the same as len (threading. Enumerate()).

In addition to using methods, the thread module also provides thread class to process threads. Thread class provides the following methods:

run():   Method used to represent thread activity.

Start(): start thread activity.

join([time]):   Wait until the thread aborts. This blocks the calling thread until the thread's join () method is called to abort - exit normally or throw an unhandled exception - or an optional timeout occurs.

isAlive():   Returns whether the thread is active.

getName():   Returns the thread name.

setName():   Set the thread name.

Custom thread

A custom thread cannot specify a target because all tasks in the custom thread are executed in the run method

The startup thread calls the start method uniformly. Do not call the run method directly, because it does not use sub threads to execute tasks

import threading

#Custom thread class

classMyThread(threading.Thread):

#Get the parameters of the receiving task through the construction method

    def__init__(self, info1, info2):

    #Call the constructor of the parent class

        super(MyThread, self).__init__() 

         self.info1 = info1 

         self.info2 = info2

    #Define tasks related to custom threads

    def test1(self):

        print(self.info1)

    deftest2(self):

        print(self.info2)

    #Perform related tasks through the run method

    def run(self):

        self.test1() 

         self.test2()

Create custom thread

my_ Thread = myThread ("test 1", "test 2")

start-up


my_thread.start()

Resource competition

Multiple threads can share global variables

Multi threads share global variables, which is convenient to share data among multiple threads

Because multiple threads operate on global variables at the same time, resource competition is easy to occur

import threading

#Define global variables

g_num =0

#Loop once to add 1 to the global variable

defsum_num1():

    for i in range(1000000):

        globalg_num 

         g_num +=1

    print("sum1:", g_num)

#Loop once to add 1 to the global variable

defsum_num2():

    for i in range(1000000):

        global g_num 

         g_num +=1

    print("sum2:", g_num)

if__name__ =='__main__':

#Create two threads

first_thread = threading.Thread(target=sum_num1) 

 second_thread = threading.Thread(target=sum_num2)

#Start thread

first_thread.start()

#Start thread

second_thread.start()

We can see that multiple threads operate data on global variables at the same time

Analysis of possible data errors caused by multithreading operating global variables at the same time

Two threads first_ Thread and second_ Thread must be on the global variable G_ Num (0 by default) adds 1. However, due to the simultaneous operation of multiple threads, the following situations may occur:

In G_ When num = 0, first_ Thread get G_ num=0。 At this time, the system sets first_ Thread is scheduled to the “sleeping” state, and second_ Thread changes to the “running” state, and T2 also gets G_ num=0

Then second_ Thread adds 1 to the obtained value and assigns it to g_ Num so that G_ num=1

Then the system puts second_ Thread is scheduled as “sleeping”, and the first_ Thread is changed to “running”. Thread T1 assigns its previous 0 plus 1 to g_ num。

This leads to the first_ Thread and first_ Threads are all right for G_ Num plus 1, but the result is still G_ num=1

Solution to multi thread resource competition

Thread synchronization

Thread synchronization: ensure that only one thread can operate global variable synchronization at the same time: cooperate with the pace and run in a predetermined order. If you finish, I’ll say it again. It’s like a walkie talkie in real life

If multiple threads operate on the same global variable at the same time, the problem of resource contention data error may occur

Thread synchronization can solve the problem of resource contention and data errors, but in this way, multiple tasks become single tasks.

mutex

The locking variable is defined in the threading module. This variable is essentially a function that can easily handle locking:

Create lock

mutex = threading.Lock()

locking

mutex.acquire()

release

mutex.release()
import threading

#Define global variables

g_num =0

#Create global mutex

lock = threading.Lock()

#Loop once to add 1 to the global variable

def sum_num1():

#Lock


    lock.acquire()

    for i in range(1000000):

        global g_num

        g_num +=1

    print("sum1:", g_num)


#Release lock

    lock.release()

#Loop once to add 1 to the global variable

def sum_num2():

#Lock

    lock.acquire()

    for iin range(1000000):

        global g_num

        g_num +=1

    print("sum2:", g_num)

#Release lock

    lock.release()

if __name__ =='__main__':

#Create two threads

    first_thread = threading.Thread(target=sum_num1)

second_thread = threading.Thread(target=sum_num2)

#Start thread

    first_thread.start()

second_thread.start()

Tip: with the mutex lock, we can’t decide which thread grabs the lock. Which thread grabs the lock and which thread executes first. Threads that don’t grab the lock need to wait

#Coupled with the mutex lock, multitasking instantly becomes a single task, and the performance will decline, that is, only one thread can execute at the same time

When a thread calls the acquire () method of the lock to obtain the lock, the lock enters the “locked” state.

Only one thread can acquire a lock at a time. If another thread attempts to obtain the lock at this time, the thread will change to the “blocked” state, which is called “blocking”. The lock will enter the “unlocked” state until the thread owning the lock calls the release () method of the lock to release the lock.

The thread scheduler selects one of the threads in the synchronous blocking state to obtain the lock and put the thread into the running state.

It ensures that a piece of key code can only be completely executed by one thread from beginning to end

Disadvantages of lock:

Multithreaded execution becomes a piece of code with locks. In fact, it can only be executed in single thread mode, which greatly reduces the efficiency

If the lock is not used well, it is easy to deadlock

deadlock

import threading

import time

#Create mutex

lock = threading.Lock()

#Take values according to subscripts to ensure that only one thread can take values at the same time

def get_value(index):

#Lock

    lock.acquire()

    print(threading.current_thread())

    my_list = [3,6,8,1]

#Judge subscript release out of bounds

    if index >=len(my_list):

        Print ("subscript out of bounds:", index)

        return

    value = my_list[index]

    print(value)

    time.sleep(0.2)

#Release lock

    lock.release()

if __name__ =='__main__':

#Simulate a large number of threads to perform value taking operations

    for i in range(30):

        sub_thread = threading.Thread(target=get_value,args=(i,))

        sub_thread.start()

When using mutex locks, you should pay attention to deadlock and release locks in appropriate places

Once a deadlock occurs, the application will stop responding

Thread priority queue

Python’s queue module provides synchronized and thread safe queue classes, including FIFO (first in first out) queue, LIFO (last in first out) queue, lifoqueue, and priority queue. These queues implement lock primitives and can be used directly in multiple threads. Queues can be used to realize synchronization between threads.

Common methods in the queue module:

Queue. Qsize() returns the size of the queue

Queue. Empty() returns true if the queue is empty, otherwise false

Queue. Full() returns true if the queue is full, otherwise false

Queue.full corresponds to the maxsize size

Queue. Get ([block [, timeout]]) gets the queue and timeout the waiting time

Queue.get_ Nowait() is equivalent to queue. Get (false)

Queue. Put (item) writes to the queue and timeout the waiting time

Queue.put_ Nowait (item) is equivalent to queue. Put (item, false)

Queue.task_ Done () after completing a task, queue. Task_ The done () function sends a signal to the queue where the task has been completed

Queue. Join () actually means waiting until the queue is empty before doing anything else

Thread, have you failed?
It won't. don't say you play programming

Recommended Today

Ajax + PHP Google search box auto fill function example code

Copy codeThe code is as follows: <html> <head> <script language=”javascript”><!– var http_request; function update(v){ if (window.XMLHttpRequest) { // Mozilla, Safari, … http_request = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE http_request = new ActiveXObject(“Microsoft.XMLHTTP”); } http_request.onreadystatechange=out; var url=”tp.phtml?worksheet=”+v.value; http_request.open(‘GET’,url,true); http_request.send(null); } function out(){ if(http_request.readyState == 4){ var div=document.getElementById(‘out’); if(http_request.responseText!=”) { div.style.display=’block’; div.innerHTML=http_request.responseText; //alert(div.innerHTML); […]