首先,要想写出本题,首先先要理解一个概念,就是Semaphore对象
Semaphore对象内部管理着一个计数器,该计数器由每个acquire()调用递减,并由每个release()调用递增。计数器永远不会低于0,当acquire()发现计数器为0的时候,线程阻塞,等待其他线程调用release()`。
import time import threading def test(): time.sleep(2) print(time.ctime()) for i in range(5): t1=threading.Thread(target=test,args=()) # 实例化一个线程 t1.start() # 启动线程执行结果:
Thu Jul 18 14:48:01 2019 Thu Jul 18 14:48:01 2019 Thu Jul 18 14:48:01 2019 Thu Jul 18 14:48:01 2019 Thu Jul 18 14:48:01 2019可以看到,程序在很短时间内生成了5个线程
如果是在主机执行IO密集型任务的时候再执行这种类型的程序时,主机有很大可能因为消耗资源过多而宕机。
这时候就可以为这段程序添加一个计数器功能,来限制一个时间点内的线程数量。
import time import threading s1=threading.Semaphore(5) #添加一个计数器 def test(): s1.acquire() #计数器获得锁,计数器值-1 time.sleep(2) #程序休眠2秒 print(time.ctime()) s1.release() #计数器释放锁,计数器值+1 for i in range(10): t1=threading.Thread(target=test,args=()) #创建线程 t1.start() #启动线程执行结果:
Thu Jul 18 14:55:54 2019 Thu Jul 18 14:55:54 2019 Thu Jul 18 14:55:54 2019 Thu Jul 18 14:55:54 2019 Thu Jul 18 14:55:54 2019 Thu Jul 18 14:55:56 2019 Thu Jul 18 14:55:56 2019 Thu Jul 18 14:55:56 2019 Thu Jul 18 14:55:56 2019 Thu Jul 18 14:55:56 2019可以看到,由于添加的信号量初始值设定为5,所以线程以每五个进行了“分隔”。
提供一个类:
class FooBar { public void foo() { for (int i = 0; i < n; i++) { print("foo"); } } public void bar() { for (int i = 0; i < n; i++) { print("bar"); } } }两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。
请设计修改程序,以确保 “foobar” 被输出 n 次。
使用两个信号量计数器,来对foo函数和bar函数分别加锁。
在调用foo函数的时候,管理foo的信号量计数器foo_lock-1,管理bar的信号量计数器bar_lock+1。 反之,在调用bar函数的时候,管理foo的信号量计数器foo_lock+1,管理bar的信号量计数器bar_lock-1。