This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!
The purpose of multithreading in a project
Specific principle I think this should be able to jump into the operating system inside a little bit of a small summary you can also find the operating system book to see, the old rules can not find the words to find my home page, there is an article about resources there are resources, of course, you can also private message me. Let’s talk about the purpose of using multithreading in our project: 1. It is very easy to share memory between threads. 2. Using multithreading for concurrent execution of multiple tasks is more efficient than using multiple processes. 3. Sometimes it saves running time, as we’ll see later
Multithreaded programming in Python is simplified by the built-in support for multithreading in the python language, rather than simply being used as a scheduler for the underlying operating system.Copy the code
Practical operation
Said so much worse than the actual hands-on practice, first import thread Special note: we don’t see the build file name and the imported packages as threading or will go wrong.
The little knowledge
import threading
Copy the code
Let’s first look at how many processes our program has
import threading
def main() :
print(threading.current_thread())
if __name__ == '__main__':
main()
Copy the code
Results:1# MyOnly One Where's yours?
Copy the code
You can also do this if you don’t have one process
import threading
def main() :
print(threading.active_count())
print(threading.enumerate())
if __name__ == '__main__':
main()
Copy the code
>>>[<_MainThread(MainThread, started 36004) >]# returns a list because I only have one so there is only one main process
Copy the code
You can also view the processes that are running
import threading
def main() :
print(threading.active_count())
print(threading.enumerate())
print(threading.current_thread())
if __name__ == '__main__':
main()
Copy the code
>1
[<_MainThread(MainThread, started 36004)>]
<_MainThread(MainThread, started 36004) >Copy the code
Create a simple thread
Let’s start with an introductionThreading. Thread ()
It is better to look at the source file to learn the functions of each module in Python. This will help you improve your programming skills:
I’ve marked the points that need attention
import threading
def first() :
print("frist active")
print("frist finish")
def main() :
first_thread=threading.Thread(target=first,name="T1")
first_thread.start()The # start sign
print("main")
if __name__ == '__main__':
main()
Copy the code
Result: Run frist Active Main frist Finish the first time and frist active Frist Finish main the second timeCopy the code
The fact that the results are different each time indicates that Frist and main are running simultaneously. If it doesn’t work that well, let’s improve it and let’s introduce
import time
Copy the code
import threading
import time
def first() :
print("frist active")
time.sleep(3)
print("frist finish")
def main() :
first_thread=threading.Thread(target=first,name="T1")
first_thread.start()
print("main")
if __name__ == '__main__':
main()
Copy the code
Result: Frist active main Frist finishCopy the code
Because by the time it gets to Frist active the Frist thread is asleep for 3 seconds while main is executing so it’s going to get this result every time.A special emphasis ontarget=first
Instead of importing the Frist function, we already know from the source file that this is done through the run () method, and I’m quoting a big name here
link
If you don’t want to do that, you can rewrite the run method in threading.Thresd to create a custom thread
class MyThread(threading.Thread) :
def __init__(self,n) :
super(MyThread,self).__init__() The run function must be written
self.n = n
def run(self) :
print('task',self.n)
time.sleep(1)
print('2s')
time.sleep(1)
print('1s')
time.sleep(1)
print('0s')
time.sleep(1)
if __name__ == '__main__':
t1 = MyThread('t1')
t2 = MyThread('t2')
t1.start()
t2.start()
Copy the code
Result: Task T1 task T2 2s 2s 1s 1s 0sCopy the code
Daemon thread
The so-called thread daemon means that the main thread will be closed whenever other subthreads finish and the main thread finishes, regardless of the execution of the thread. That is: the main thread does not wait for the daemon thread to finish executing before closing.Copy the code
If it’s hard to understand, let’s look at an example
import threading
import time
def first() :
print("frist active")
time.sleep(3)
print("frist finish")
def second() :
print("second active")
print("second finish")
def main() :
first_thread=threading.Thread(target=first,name="T1")
second_thresd=threading.Thread(target=second,name="T2")
first_thread.setDaemon(True)# Always start before start ()
first_thread.start()
second_thresd.start()
print("main")
if __name__ == '__main__':
main()
Copy the code
Result Frist active second Active second FinishJiemeijieshu mainCopy the code
When both the main thread and the other subthreads terminate, the program terminates regardless of whether the daemon thread “first_thread” terminates. This is the case when you set second_thresd as the daemon thread
import threading
import time
def first() :
print("frist active")
time.sleep(3)
print("frist finish")
def second() :
print("second active")
print("second finish")
def main() :
first_thread=threading.Thread(target=first,name="T1")
second_thresd=threading.Thread(target=second,name="T2")
second_thresd.setDaemon(True)# Always start before start ()
first_thread.start()
second_thresd.start()
print("main")
if __name__ == '__main__':
main()
Copy the code
frist active
second active
second finish
main
frist finish # Although it takes three seconds to output this
Copy the code
The main process waits for the child process to finish
In order for the main thread to finish after the daemon thread finishes executing, we can use the join method to make the main thread wait for the child thread to execute
import threading
import time
def first() :
print("frist active")
time.sleep(3)
print("frist finish")
def second() :
print("second active")
print("second finish")
def main() :
first_thread=threading.Thread(target=first,name="T1")
second_thresd=threading.Thread(target=second,name="T2")
first_thread.start()
second_thresd.start()
first_thread.join()
print("main")
if __name__ == '__main__':
main()
Copy the code
Results: Frist Active Second Active Second Finish Frist Finish main Frist Active Second Active second Finish main frist finishCopy the code
Shared features of global variables
Here we define A global variable A
import threading
import time
def first() :
global A
print("frist active")
time.sleep(3)
A=A+3
print("frist:%d"%A)
print("frist finish")
def second() :
global A
print("second active")
A=A+6
print("second:%d"%A)
print("second finish")
def main() :
global A
first_thread=threading.Thread(target=first,name="T1")
second_thresd=threading.Thread(target=second,name="T2")
first_thread.start()
second_thresd.start()
#first_thread.join()
print("main")
A=A+3
print("mian:%d"%A)
if __name__ == '__main__':
A=0
main()
Copy the code
Let’s look at the results
frist active
second active
second:6
second finish
main
mian:9
frist:12
frist finish
Copy the code
The lock
As you can see from the example above, when the value of A is printed, the resources between different processes are shared. This leads to the situation where the value of variable A is not fixed and dirty data is generated.
In the absence of a mutex, assuming the account has $10,000, you can deposit and withdraw money at the same time with a balance of $11,000. I’d be happy to but the bank wouldn’t let me. To avoid this, let’s introduce the concept of locking. Let’s briefly introduce a few common ones in programming.
The mutex
import threading
import time
def first() :
global A,lock
lock.acquire()
print("frist active")
time.sleep(3)
A=A+3
print("frist:%d"%A)
print("frist finish")
lock.release()
def second() :
global A,lock
lock.acquire()
print("second active")
A=A+6
print("second:%d"%A)
print("second finish")
lock.release
def main() :
global A,lock
lock=threading.Lock()
first_thread=threading.Thread(target=first,name="T1")
second_thresd=threading.Thread(target=second,name="T2")
first_thread.start()
second_thresd.start()
#first_thread.join()
print("main")
A=A+3
print("mian:%d"%A)
if __name__ == '__main__':
A=0
main()
Copy the code
The results of
frist active
main
mian:3
frist:6
frist finish
second active
second:12
second finish
Copy the code
Isn’t that more comfortable? If it’s not obvious let’s do another one
import threading
import time
def first() :
global A,lock
lock.acquire()
print("frist active")
time.sleep(3)
A=A+3
print("frist1:%d"%A)
A = A + 3
print("frist2:%d" % A)
print("frist finish")
lock.release()
def second() :
global A,lock
lock.acquire()
print("second active")
A=A+6
print("second1:%d"%A)
A=A+6
print("second2:%d"%A)
print("second finish")
lock.release()
def main() :
global A,lock
lock=threading.Lock()
first_thread=threading.Thread(target=first,name="T1")
second_thresd=threading.Thread(target=second,name="T2")
first_thread.start()
second_thresd.start()
#first_thread.join()
print("main")
A=A+3
print("mian:%d"%A)
if __name__ == '__main__':
A=0
main()
Copy the code
The results of
frist active
main
mian:3
frist1:6
frist2:9
frist finish
second active
second1:15
second2:21Second finish Frist active second active second1:6
second2:12
second finish
main
mian:15
frist1:18
frist2:21
frist finish
Copy the code
Obviously, the results are messy when you remove the lock
A semaphore
I believe that I have a certain understanding of the operating system, and I have semaphore in mind when I mentioned locking, after all, the exam questions often appear, synchronization, mutex and semaphore mechanism. We have to say a semaphore lock, in fact, the rule is simple if you now, to get married in China you can only marry a wife, even though you can go to find another woman but they cannot be called a wife they will be called a little three, mistress, and so on, the wife here in China, the semaphore is a = = = = can have only one, the other can’t again.
import threading
import time
def run(n,semaphore) :
semaphore.acquire() # lock
time.sleep(3)
print('run the thread:%s\n' % n)
semaphore.release() # release
if __name__== '__main__':
num=0
semaphore = threading.BoundedSemaphore(3) # Allow up to 3 threads to run simultaneously
for i in range(10):
t = threading.Thread(target=run,args=('t-%s' % i,semaphore))
t.start()
whilethreading.active_count() ! =1:
pass
else:
print('----------all threads done-----------')
Copy the code
The results of
run the thread:t-2
run the thread:t-1
run the thread:t-0
run the thread:t-3
run the thread:t-5
run the thread:t-4
run the thread:t-6
run the thread:t-7
run the thread:t-8
run the thread:t-9
----------all threads done-----------
Copy the code
Give some resources
If you want to continue to explore the thread and you don’t have the resources, I have a book on the operating system, you can send me a private message oh, well, that’s all for today’s study. Don’t forget to click “like”