1. Introduction to thread precautions
Execution between threads is out of order
The main thread will wait for the execution of all child threads to end
Sharing global variables between threads
There was an error sharing global variable data between threads
2. The execution between threads is out of order
import threading import time def task(): time.sleep(1) print("Current thread:", threading.current_thread().name) if __name__ == '__main__': for _ in range(5): sub_thread = threading.Thread(target=task) sub_thread.start() results of enforcement: Current thread: Thread-1 Current thread: Thread-2 Current thread: Thread-4 Current thread: Thread-5 Current thread: Thread-3
explain:
The execution between threads is disordered, which is determined by cpu scheduling. Which thread is scheduled by cpu will execute first. Threads without scheduling cannot execute.
The execution between processes is also disordered. It is determined by the operating system scheduling. Which process the operating system schedules will be executed first. Processes without scheduling cannot be executed.
3. The main thread will wait for the execution of all sub threads to end
If we now create a sub thread, it will take about 2.5 seconds for the sub thread to execute. Now let the main thread execute for 1 second and exit the program. Check the execution results. The example code is as follows:
import threading import time #Test whether the main thread will wait for the execution of the child thread before exiting the program def show_info(): for i in range(5): print("test:", i) time.sleep(0.5) if __name__ == '__main__': sub_thread = threading.Thread(target=show_info) sub_thread.start() # Main thread delay 1 second time.sleep(1) print("over") results of enforcement: test: 0 test: 1 over test: 2 test: 3 test: 4
explain:
From the execution results of the above code, we can know that the main thread will wait for the execution of all sub threads to end
What if we let the main thread execute for one second and the sub thread is destroyed and no longer executed?
We can set the guard main thread
Guard main thread:
Guarding the main thread means that the main thread exits and the child thread is destroyed and no longer executed
There are two ways to set the guard main thread:
threading.Thread(target=show_info, daemon=True)
Thread object setDaemon(True)
Main code of daemon thread:
import threading import time #Test whether the main thread will wait for the execution of the child thread before exiting the program def show_info(): for i in range(5): print("test:", i) time.sleep(0.5) if __name__ == '__main__': # Create a child thread to guard the main thread # daemon=True guard the main thread # Guard main thread mode 1 sub_thread = threading.Thread(target=show_info, daemon=True) # It is set as the guardian main thread. After the main thread exits, the sub thread directly destroys the code that no longer executes the sub thread # Guard main thread mode 2 # sub_thread.setDaemon(True) sub_thread.start() # Main thread delay 1 second time.sleep(1) print("over") results of enforcement: test: 0 test: 1 over
3. Sharing global variables between threads
Requirements:
Define a global variable of list type
Create two sub threads to execute the task of adding data to the global variable and the task of reading data from the global variable respectively
Check whether global variable data is shared between threads
import threading import time #Define global variables my_list = list() #Write data task def write_data(): for i in range(5): my_list.append(i) time.sleep(0.1) print("write_data:", my_list) # Read data task def read_data(): print("read_data:", my_list) if __name__ == '__main__': # Create a thread to write data write_thread = threading.Thread(target=write_data) # Create a thread to read data read_thread = threading.Thread(target=read_data) write_thread.start() # delayed # time.sleep(1) # After the main thread waits for the write thread to finish executing, the code continues to execute write_thread.join() print("Start reading data") read_thread.start() results of enforcement: write_data: [0, 1, 2, 3, 4] Start reading data read_data: [0, 1, 2, 3, 4]
4. There is an error in sharing global variable data between threads
Requirements:
Define two functions to realize 1 million cycles, and add 1 to the global variable every cycle
Create two sub threads to execute the corresponding two functions and view the calculated results
import threading #Define global variables g_num = 0 #Loop once to add 1 to the global variable def sum_num1(): for i in range(1000000): global g_num g_num += 1 print("sum1:", g_num) #Loop once to add 1 to the global variable def sum_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() results of enforcement: sum1: 1210949 sum2: 1496035
Note:
Multithreading has an error in operating data on global variables at the same time
Error analysis:
Two threads first_thread and second_thread must be set to 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 point, the system sets the 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_ Turn thread 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 global variable data error:
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
Thread synchronization mode:
Thread wait (join)
mutex
Example code of thread waiting:
import threading #Define global variables g_num = 0 #Loop 1000000 times, adding 1 to the global variable each time def sum_num1(): for i in range(1000000): global g_num g_num += 1 print("sum1:", g_num) #Loop 1000000 times, adding 1 to the global variable each time def sum_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() # The main thread waits for the first thread to execute, and then the code continues to execute, allowing it to execute the second thread # Thread synchronization: after one task is completed, another task can be executed. At the same time, only one task is executing first_thread.join() # Start thread second_thread.start() results of enforcement: sum1: 1000000 sum2: 2000000
5. Summary
Thread execution is out of order
By default, the main thread will wait for the execution of all sub threads to end. The purpose of setting the guard main thread is to exit the main thread and destroy the sub threads.
The advantage of sharing global variables between threads is that the data of global variables can be shared.
Sharing global variables between threads may lead to data errors. Thread synchronization can be used to solve this problem.
Thread wait (join)