首页 > 技术文章 > python3 进程信号量semaphore

lilyxiaoyy 2019-06-06 16:14 原文

提前设定好,一个房间只有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>

 

推荐阅读