[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 
View Code

 

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 
View Code

 

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 
View Code

 

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
View Code

 

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 
View Code

 

输出说明 :

基准输出 , 执行正常的逻辑,每隔2秒执行2个线程,分布对共享变量加1,逻辑正常

case1  睡眠1秒 ,  被其他线程 修改了 数据

case2    计算 密集型,同case1

case3   输出少了 字符 , 逻辑正常

case4   输出大量字符  ,通case1

 

posted @ 2018-09-11 21:30  sunzebo  阅读(226)  评论(0编辑  收藏  举报