[b0032] python 归纳 (十七)_线程同步_信号量Semaphore
代码:
# -*- coding: utf-8 -*- """ 多线程并发同步 ,使用信号量threading.Semaphore 逻辑: 多个线程,对同一个共享变量 ,加1,并且各自打印加1前、加1后的值 总结: 信号量也提供acquire方法和release方法,每当调用acquire方法的时候,如果内部计数器大于0,则将其减1, 如果内部计数器等于0,则会阻塞该线程,知道有线程调用了release方法将内部计数器更新到大于1位置 1. 个人感觉,信号量类似锁,创建2个大小的信号量,类似创建2把锁 2. 信号量好像可以实现进程Pool,做到任何时候最多有多少个线程执行某些逻辑 3. 使用 信号量,要很小心,可能存在多个线程操作同一份数据 ,导致不一致 比如 case1,case2,case3,case4 使用: 1. 创建指定大小的信号量对象 sem = threading.Semaphore(value=2) 2. 在必要的地方获得信号量,一般是操作共享数据 sem.acquire() 3. 结束的地方,及时释放信号量 sem.release() 参考: """ import threading import time # 计算pi def calc_pi(): from sys import stdout scale = 10000 maxarr = 2800 arrinit = 2000 carry = 0 arr = [arrinit] * (maxarr + 1) for i in xrange(maxarr, 1, -14): total = 0 for j in xrange(i, 0,-1): total = (total * j) + (scale * arr[j]) arr[j] = total % ((j * 2) - 1) total = total / ((j * 2) - 1) # stdout.write("%04d" % (carry + (total / scale))) carry = total % scale # 打印一个字符 def show1(): print "h" # 打印很多字符 def show2(): print "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" class Num: """ 多线程操作的共享数据和方法封装 数据 num 方法 add 加1 """ def __init__(self): self.num = 0 self.sem = threading.Semaphore(value=2) # 大小=2的信号量 def add(self): self.sem.acquire() # 获取信号量, 内部计数器-1 begin = self.num # 加1前的值 self.num += 1 # time.sleep(1) # case1 睡眠1秒 # calc_pi() # case2 执行计算密集型运行 # show1() # case3 打印很少字符 # show2() # case4 打印很多字符 end = self.num # 加1后的值 time.sleep(2) # 各个线程睡眠2秒,方便看程序执行效果 self.sem.release() # 释放信号量,内部计数器+1 return (begin,end) # 共享数据 n = Num() class jdThread(threading.Thread): """多线程代码,对共享数据加1,并且打印 """ def __init__(self,item): threading.Thread.__init__(self) self.item = item def run(self): value = n.add() # 加1,拿到返回值 (处理前,处理后) print "\n", time.strftime('%M:%S',time.localtime(time.time())), " "+str(value[0])+"->"+str(value[1])+" " if __name__ == "__main__": # 启动20个线程 for item in range(20): t = jdThread(item) t.start() print "main end"
输出:
基准,以上代码执行
main end
03:58 0->1
03:58 1->2
04:00 2->3
04:00 3->4
04:02 4->5
04:02 5->6
04:04 6->7
04:04 7->8
04:06 8->9
04:06 9->10
04:08 10->11
04:08 11->12
04:10 12->13
04:10 13->14
04:12 14->15
04:12 15->16
04:14 16->17
04:14 17->18
04:16 18->19
04:16 19->20
case1,多执行case1
main end 07:48 07:48 1->2 0->2 07:51 2->4 07:51 3->4 07:54 4->6 07:54 5->6 07:57 6->8 07:57 7->8
case2
main end 08:1808:18 0->2 1->2 08:21 3->4 08:21 2->4 08:23 5->6 08:23 4->6 08:26 7->8 08:26 6->8
case3
h h main end 08:48h 0->1 h 08:48 1->2 h08:50 2->3 08:50 h 3->4 08:52h 4->5 h 08:52 5->6 h08:54 6->7 08:54 h 7->8 h08:56 8->9 h 08:56 9->10 08:58 h 10->11 08:58h 11->12 09:00h 12->13 09:00 13->14 h h 09:02 14->15 09:02 h 15->16 h09:04 16->17 09:04 h 17->18 09:06 18->19 09:06 19->20 Process finished with exit code 0
case4
D:\Programs\Anaconda\python.exe D:/1_practice/python/projects/downloads_modify/归类/并发/thread_sync_2.py hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh main end 10:55 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 1->2 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh10:55 0->1 10:57hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 2->3 10:57hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 3->4 10:59 4->5 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh10:59hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 5->6 11:01 7->8 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 11:01 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 6->8 11:03 8->10 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh11:03hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 9->10 11:05 11->12 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh11:05 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 10->12 11:07 11:07 12->14 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 13->14 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 11:09 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 14->16 11:09hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 15->16
输出说明 :
基准输出 , 执行正常的逻辑,每隔2秒执行2个线程,分布对共享变量加1,逻辑正常
case1 睡眠1秒 , 被其他线程 修改了 数据
case2 计算 密集型,同case1
case3 输出少了 字符 , 逻辑正常
case4 输出大量字符 ,通case1
写满200篇博文再说