Objective record
1. Semaphore Semaphore introduction
2. threading.Semaphore
2.1 threading.Semaphore Properties and methods
2.1.1 threading.Semaphore Construction method
2.1.2 threading.Semaphore Properties and methods
2.2 threading.Semaphore Use demonstration
2.2.1 Use threading.Semaphore Control the maximum number of threads
2.2.2 threading.Semaphore Use with Reduce the amount of code
3. threading.BoundedSemaphore
3.1 BoundedSemaphore and Semaphore The difference between
3.2 threading.BoundedSemaphore Properties and methods
3.3 threading.BoundedSemaphore Use demonstration
Python Multithreaded programming Directory
Python Multithreaded programming -01-threading The module first
Python Multithreaded programming -02-threading modular - Use of locks
Python Multithreaded programming -03-threading modular - Condition
Python Multithreaded programming -04-threading modular - Event
Speak in general , Multi process / Semaphore mechanism in threads , It can be understood that there are two tuples (S,Q),S Is an integer variable , The initial value is non negative ,Q Is a waiting queue whose initial state is empty , This mechanism is designed to implement processes / Synchronization and mutual exclusion in threads .
Some students may not have touched Semaphore The concept of semaphore , You can simply refer to this article .
2.4 CPU management -- Semaphores and PV operation _ no pains,no gains -CSDN Blog . Although this text is aimed at the process , But in multithreaded programming , The design intent and use mechanism of semaphores are the same .
threading.Semaphore It can be understood as a built-in counter , When calling acquire Method time built-in counter -1, Corresponding to the application resources ; call release Method time built-in counter +1, This corresponds to the release of available resources .
s=threading.Semaphore(value=1),value Indicates the maximum count of semaphores , The default is 1; In code design, it can be understood as the number of available resources .
acquire(self, blocking=True,
timeout=None)
Get a semaphore , Its built-in counter -1;
If the call does not use parameters : If the counter is greater than when calling 0 be -1 And return immediately ; If it is zero hour , Block the current thread , Wait for another thread to call release() To free resources to be greater than zero . This is done through appropriate interlocks , So if more than one acquire() Call blocked ,release() Only one of these calls will wake up . The implementation may choose one at random , So it is not reliable which blocked threads are awakened , No return value in this case .
If you use parameters when calling :
a) blocking=True Consistent with the above , Return immediately upon success True
b) blocking=False, So the counter is zero , It won't block , It's about returning immediately False.
c) timeout=n, Not equal to None, So the most blocking n second ,n No semaphore obtained within seconds , Then return to False
2mro() Built in mro Method , The method resolution order of the return type .3release(self) Release resources , Semaphore counter +1, If the original semaphore counter is equal to 0, Then wake up a waiting thread .A program is designed below ,semaphore Designed the most 5 Threads can be started at the same time , The first n Threads sleep n-1 second , And then again release resources ; In this way, you can see that it starts at the same time in the first second 6 Threads ( The first thread is immediately released , So the sixth got the resources immediately ), Next, a thread gets resources every second .
import threading
import time
s=threading.Semaphore(5)
thread_list=[]
def fun(n):
s.acquire()
print(time.ctime(),"===>",n)
time.sleep(n)
s.release()
for tmp in range(10):
t=threading.Thread(target=fun,args=(tmp,))
thread_list.append(t)
for tmp in range(10):
thread_list[tmp].start()
The operation results are as follows :
Use with usage , It can be omitted. release() Method , The result is the same .
s=threading.Semaphore(5)
thread_list=[]
def fun2(n):
with s:
print(time.ctime(),"===>",n)
time.sleep(n)
for tmp in range(10):
t=threading.Thread(target=fun2,args=(tmp,))
thread_list.append(t)
for tmp in range(10):
thread_list[tmp].start()
for tmp in range(10):
thread_list[tmp].join()
print("All done!")
The operation results are as follows :
BoundedSemaphore and Semaphore The difference between is threading.BoundedSemaphore Will be used too much release() Wrong time " ValueError: Semaphore released too many times ".
threading.BoundedSemaphore Properties and methods of threading.Semaphore Very similar , I won't repeat .
The code is designed as follows , When the threading.BoundedSemaphore When releasing repeatedly , It will report an error .
s=threading.Semaphore(3)
bs=threading.BoundedSemaphore(3)
thread_list=[]
def fun(n):
with s:
print(time.ctime(),"===>",n)
time.sleep(n)
# Even if with The statement will automatically release, Also show the release of again
s.release()
def fun2(n):
with bs:
print(time.ctime(),"===>",n)
time.sleep(n)
bs.release()
for tmp in range(5):
t=threading.Thread(target=fun,args=(tmp,))
thread_list.append(t)
for tmp in range(5):
thread_list[tmp].start()
#
thread_list=[]
time.sleep(6)
for tmp in range(5):
t=threading.Thread(target=fun2,args=(tmp,))
thread_list.append(t)
for tmp in range(5):
thread_list[tmp].start()
print("All done!")
Running results
'''
If everyone thinks it's ok , Please order a praise or collection , Think of a blog to increase popularity , Thank you very much !
'''