提前设定好,一个房间只有4个床(计数器现在为4),那么同时只能四个人进来,谁先来的谁先占一个床(acquire,计数器减1),4个床满了之后(计数器为0了),第五个人就要等着,等其中一个人出来(release,计数器加1),他就去占用那个床了。
互斥锁同时只允许一个线程更改数据,而信号量Semaphore是同时允许一定数量的线程更改数据 。
假设商场里有4个迷你唱吧,所以同时可以进去4个人,如果来了第五个人就要在外面等待,等到有人出来才能再进去玩。
实现:
信号量同步基于内部计数器,每调用一次acquire(),计数器减1;每调用一次release(),计数器加1.当计数器为0时,acquire()调用被阻塞。这是迪科斯彻(Dijkstra)信号量概念P()和V()的Python实现。信号量同步机制适用于访问像服务器这样的有限资源。
信号量与进程池的概念很像,但是要区分开,信号量涉及到加锁的概念
# -*- coding: utf-8 -*-
import os
import time
from multiprocessing import Process
def go_ktv(i):
print("user%s正在....ktv.子进程(%s)" % (i, os.getpid()))
time.sleep(2)
if __name__ == '__main__':
'''开启20个进程,操作系统可以调度4个cpu去执行,进程的调用比线程的开销大些'''
start_time = time.time()
p_lst = []
for i in range(20):
p = Process(target=go_ktv, args=(i,))
p.start()
p_lst.append(p)
[pp.join() for pp in p_lst]
print("运行时间: %s.主进程<%s>" % ((time.time() - start_time), os.getpid()))
# user0正在....ktv.子进程(5496)
# user1正在....ktv.子进程(6996)
# user3正在....ktv.子进程(6328)
# user2正在....ktv.子进程(1064)
# user4正在....ktv.子进程(4844)
# user7正在....ktv.子进程(7804)
# user5正在....ktv.子进程(7688)
# user8正在....ktv.子进程(7136)
# user6正在....ktv.子进程(7824)
# user9正在....ktv.子进程(7812)
# user10正在....ktv.子进程(8148)
# user11正在....ktv.子进程(2556)
# user13正在....ktv.子进程(4744)
# user15正在....ktv.子进程(6232)
# user14正在....ktv.子进程(5168)
# user16正在....ktv.子进程(6444)
# user12正在....ktv.子进程(2616)
# user17正在....ktv.子进程(5188)
# user18正在....ktv.子进程(8088)
# user19正在....ktv.子进程(7224)
# 运行时间: 3.2611865997314453.主进程<6936>
# -*- coding: utf-8 -*-
import os
import time
from multiprocessing import Pool
def go_ktv(i):
print("user%s正在....ktv.子进程(%s)" % (i, os.getpid()))
time.sleep(2)
if __name__ == '__main__':
'''创建进程池,进程的容量默认是4,
如果总进程的数量超过4,就会自动排队等待,一次可执行4个进程,进程池内的进程结束一个,就会自动进来一个新的进程,重用原来的进程号,节省开销'''
start_time = time.time()
pool = Pool()
p_lst = []
for i in range(20):
pool.apply_async(go_ktv, args=(i,))
pool.close()
pool.join()
print("运行时间: %s.主进程<%s>" % ((time.time() - start_time), os.getpid()))
# user0正在....ktv.子进程(7396)
# user1正在....ktv.子进程(1760)
# user2正在....ktv.子进程(8000)
# user3正在....ktv.子进程(4120)
# user4正在....ktv.子进程(7396)
# user5正在....ktv.子进程(1760)
# user6正在....ktv.子进程(8000)
# user7正在....ktv.子进程(4120)
# user8正在....ktv.子进程(7396)
# user9正在....ktv.子进程(1760)
# user10正在....ktv.子进程(8000)
# user11正在....ktv.子进程(4120)
# user12正在....ktv.子进程(7396)
# user13正在....ktv.子进程(1760)
# user14正在....ktv.子进程(8000)
# user15正在....ktv.子进程(4120)
# user16正在....ktv.子进程(7396)
# user17正在....ktv.子进程(1760)
# user18正在....ktv.子进程(8000)
# user19正在....ktv.子进程(4120)
# 运行时间: 10.851620435714722.主进程<7428>
# -*- coding: utf-8 -*-
import os
import time
from multiprocessing import Process, Semaphore
def go_ktv(i, sem):
with sem:
print("user%s正在....ktv.子进程(%s)" % (i, os.getpid()))
time.sleep(2)
if __name__ == '__main__':
'''开启20个进程,一次可执行4(信号量容量)个进程,相当于添加另一个互斥锁'''
start_time = time.time()
sem = Semaphore(4)
p_lst = []
for i in range(20):
p = Process(target=go_ktv, args=(i, sem))
p.start()
p_lst.append(p)
[pp.join() for pp in p_lst]
print("运行时间: %s.主进程<%s>" % ((time.time() - start_time), os.getpid()))
# user0正在....ktv.子进程(3660)
# user1正在....ktv.子进程(7188)
# user3正在....ktv.子进程(7268)
# user2正在....ktv.子进程(7568)
# user5正在....ktv.子进程(2896)
# user6正在....ktv.子进程(2852)
# user7正在....ktv.子进程(376)
# user4正在....ktv.子进程(7532)
# user9正在....ktv.子进程(8188)
# user10正在....ktv.子进程(1444)
# user12正在....ktv.子进程(6304)
# user11正在....ktv.子进程(6776)
# user14正在....ktv.子进程(6992)
# user13正在....ktv.子进程(7248)
# user8正在....ktv.子进程(6820)
# user17正在....ktv.子进程(6308)
# user15正在....ktv.子进程(8020)
# user18正在....ktv.子进程(4312)
# user16正在....ktv.子进程(2724)
# user19正在....ktv.子进程(7516)
# 运行时间: 10.443597078323364.主进程<2560>