import time
import threading
def task1(arg):while True:print("--%s--"% arg)
time.sleep(0.1)
def task2(arg):while True:print("--%s--"% arg)
time.sleep(0.1)
def main():
t1 = threading.Thread(target = task1,args =(1,))
t2 = threading.Thread(target = task2,args =(2,))
t1.start()
t2.start()if __name__ =='__main__':main()"""
--1----2----1----2----1----2----1----2----1----2--...."""
print(threading.enumerate())
Multi-tasking program development can be completed by using the threading module. In order to make the encapsulation of each thread more perfect, when using the threading module, a new subclass is often defined, as long as the threading.Thread is inherited, and then re Write the run method.
# coding=utf-8import threading
import time
classMyThread(threading.Thread):
def run(self):for i inrange(3):
time.sleep(1)
# The name attribute holds the name of the current thread
msg = self.name+':'+str(i)print(msg)if __name__ =='__main__':
t =MyThread()
t.start()
Python's threading.Thread class has a run method, which is used to define the function of the thread, which can be overridden in your thread class. After creating your own thread instance, you can start the thread through the start method of the Thread class and hand it over to the python virtual machine for scheduling. When the thread gets a chance to execute, it will call the run method to execute the thread.
from threading import Thread
import time
def work1(nums):
nums.append(44)print("----in work1---",nums)
def work2(nums):
# Delay for a while to ensure that things in the t1 thread are done
time.sleep(1)print("----in work2---",nums)
g_nums =[11,22,33]
t1 =Thread(target=work1, args=(g_nums,))
t1.start()
t2 =Thread(target=work2, args=(g_nums,))
t2.start()
# operation result:
#
# - - - - in work1---[11,22,33,44]
# - - - - in work2---[11,22,33,44]
When multiple threads modify a certain shared data almost at the same time, synchronization control is required
Thread synchronization can ensure that multiple threads safely access competing resources. The simplest synchronization mechanism is to introduce a mutex lock.
Mutex locks introduce a state for resources: locked/unlocked
When a thread wants to change shared data, lock it first. At this time, the status of the resource is "locked" and other threads cannot change it; until the thread releases the resource and changes the status of the resource to "non-locked", other threads can Lock the resource again. The mutex lock ensures that only one thread performs write operations at a time, thereby ensuring the correctness of the data in the case of multiple threads.
The Lock class is defined in the threading module, which can handle locking conveniently:
# Create lock
mutex = threading.Lock()
# locking
mutex.acquire()
# freed
mutex.release()
import threading
import time
g_num =0
def test1(num):
global g_num
for i inrange(num):
mutex.acquire() #Locked
g_num +=1
mutex.release() #Unlock
print("---test1---g_num=%d"%g_num)
def test2(num):
global g_num
for i inrange(num):
mutex.acquire() #Locked
g_num +=1
mutex.release() #Unlock
print("---test2---g_num=%d"%g_num)
# Create a mutex
# The default is unlocked
mutex = threading.Lock()
# Create 2 threads, let them each to g_num plus 1000000 times
p1 = threading.Thread(target=test1, args=(1000000,))
p1.start()
p2 = threading.Thread(target=test2, args=(1000000,))
p2.start()
# Wait for the calculation to complete
whilelen(threading.enumerate())!=1:
time.sleep(1)print("The final result after two threads operate on the same global variable is:%s"% g_num)
operation result
- - - test1---g_num=1909909---test2---g_num=The final result after 20000002 threads operate on the same global variable is:2000000
You can see the final result. After adding the mutex, the result is in line with expectations.
When a thread calls the acquire() method of the lock to acquire the lock, the lock enters the "locked" state.
Only one thread can acquire the lock at a time. If another thread tries to acquire the lock at this time, the thread will become "blocked" state, called "blocked", until the thread that owns the lock calls the lock's release() method to release the lock, the lock enters the "unlocked" state .
The thread scheduler selects one of the threads in the synchronized blocking state to obtain the lock, and causes the thread to enter the running state.
The benefits of locks:
Disadvantages of locks:
Recommended Posts