The third task of Python advanced training (winter vacation)

Posted by legohead6 on Sat, 08 Jan 2022 06:10:13 +0100

Multithreading

Distinction between threads and processes

1. Thread is the smallest unit of program execution, and process is the smallest unit of resources allocated by the operating system
2. A process is composed of one or more threads. Threads are different execution routes of code in a process
3. Processes are independent of each other, but each thread in the same process shares the memory space of the program (such as code segment, data set, heap, etc.) and some process level resources (such as opening files and signals, etc.)

Functional: calling_ Start in thread module_ new_ Thread() function to generate a new thread. The syntax is as follows:

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

Parameter Description:

Function - thread function.
args - the parameter passed to the thread function. It must be of type tuple.
kwargs - optional parameter.

example

import threading
import time

def test(x):
    start_time = time.time()
    print(x)
    time.sleep(3)
    print(f"test()The function is running{time.time() - start_time}second\n")
# test(2)
# test(3)
t1 = threading.Thread(target=test,args=(3,))
t2 =threading.Thread(target=test,args=(6,))
t1.start()
t2.start()

result

3
6
test()The function ran for a total of 3.002709150314331 second
test()The function ran for a total of 3.002709150314331 second

Thread module

The threading module contains_ In addition to all methods in the thread module, other methods are also provided:

  • 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, with the same result 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(): the 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(): sets the thread name.

example

import threading
import time

class MyThread(threading.Thread):
    def __init__(self,n):
        super(MyThread,self).__init__()
        self.n = n

    def run(self):
        print("Create multithreading as a thread class",self.n)

t1 = MyThread(1)
t2 = MyThread(2)
t1.start()
t2.start()

result

Create multithread 1 as a thread class
 Create multithreading as a thread class 2

Thread synchronization

If multiple threads modify a data together, unexpected results may occur. In order to ensure the correctness of the data, multiple threads need to be synchronized.

Simple thread synchronization can be realized by using Lock and Rlock of Thread objects. Both objects have acquire and release methods. For data that needs to be operated by only one thread at a time, its operation can be placed between acquire and release methods.
The advantage of multithreading is that it can run multiple tasks at the same time (at least it feels like this). However, when threads need to share data, there may be a problem of data synchronization.

Consider this situation: all elements in a list are 0, the thread "set" changes all elements to 1 from back to front, and the thread "print" is responsible for reading and printing the list from front to back.

Then, when the thread "set" starts to change, the thread "print" will print the list, and the output will be half 0 and half 1, which is the asynchrony of data. In order to avoid this situation, the concept of lock is introduced.

The lock has two states - locked and unlocked. Whenever a thread, such as "set", wants to access shared data, it must first obtain a lock; If another thread, such as "print", has been locked, the thread "set" is suspended, that is, synchronization blocking; Wait until the thread "print" is accessed and the lock is released, and then let the thread "set" continue.

After such processing, when printing the list, either all 0 or all 1 will be output, and the embarrassing scene of half 0 and half 1 will not appear again.

example

import threading

def run():
    global x
    lock.acquire()
    x += 1
    lock.release()

if __name__ == '__main__':
    x = 0
    l1 = []
    lock = threading.Lock()
    for i in range(100):
        t = threading.Thread(target=run())
        t.start()
        l1.append(t)

    for t in l1:
        t.join()

    print(x)

result

100

Process finished with exit code 0

Topics: Python Pycharm Back-end Multithreading