python 线程同步_Python-线程同步

1、线程同步

线程同步,线程间协同,通过某种技术,让一个线程访问某些数据时,其他线程不能访问这些数据,直到该线程完成对数的操作做。

不同操作系统实现技术有所不同,有 临界区(Critical Section),互斥量(Mutex), 信号量(Semaphore),时间Event等

2、Event

Even事件,是线程间通信机制中最简单的实现,使用一个内部的标记flag,通过flag的True或False的变化来进行操作。

名称

含义

set()

标记设置为True

clear()

标记设置为False

is_set()

标记是否为True

wait(timeout=None)

设置等待标记为True的时长,None为无限等待,等到返回True,未等到超时了,返回False

测试:需求:老板雇了一个员工,让他生成杯子,老板一直等待这个工人,知道生产了10个杯子。

1、普通线程实现:

ContractedBlock.gif

ExpandedBlockStart.gif

1 importthreading2 importtime3

4 flag =False5

6 def worker(count=10):7 print('im working')8 globalflag9 cpus =[]10 whileTrue:11 time.sleep(0.1)12 cpus.append(1)13 if len(cpus) > 10:14 flag =True15 break

16 print(cpus)17

18 defboss():19 globalflag20 whileTrue:21 time.sleep(2)22 ifflag:23 print('good job')24 break

25

26 w = threading.Thread(target=worker)27 b = threading.Thread(target=boss)28 w.start()29 b.start()

View Code

结果:

ContractedBlock.gif

ExpandedBlockStart.gif

1 im working2 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]3 good job4

5 Process finished with exit code 0

View Code

2、利用Event 类实现:

ContractedBlock.gif

ExpandedBlockStart.gif

1 from threading importEvent, Thread2 importlogging3 importtime4

5 FORMAT = '%(asctime)s %(threadName)s %(thread)d %(message)s'

6 logging.basicConfig(format=FORMAT, level=logging.INFO)7

8 defboss(event:Event):9 logging.info('boss')10 event.wait()11 logging.info('good job')12

13 def worker(event:Event, count=10):14 logging.info('working')15 cups =[]16 whileTrue:17 logging.info('make 1')18 time.sleep(0.5)19 cups.append(1)20 if len(cups) >=count:21 event.set()22 break

23 logging.info('finished {}'.format(cups))24

25 event =Event()26 w = Thread(target=worker, args=(event,))27 b = Thread(target=boss, args=(event,))28 w.start()29 b.start()

View Code

结果:

ContractedBlock.gif

ExpandedBlockStart.gif

1 2018-10-12 10:58:11,515 Thread-1 8448working2 2018-10-12 10:58:11,515 Thread-1 8448 make 1

3 2018-10-12 10:58:11,515 Thread-2 1064boss4 2018-10-12 10:58:12,030 Thread-1 8448 make 1

5 2018-10-12 10:58:12,545 Thread-1 8448 make 1

6 2018-10-12 10:58:13,060 Thread-1 8448 make 1

7 2018-10-12 10:58:13,574 Thread-1 8448 make 1

8 2018-10-12 10:58:14,089 Thread-1 8448 make 1

9 2018-10-12 10:58:14,604 Thread-1 8448 make 1

10 2018-10-12 10:58:15,119 Thread-1 8448 make 1

11 2018-10-12 10:58:15,634 Thread-1 8448 make 1

12 2018-10-12 10:58:16,148 Thread-1 8448 make 1

13 2018-10-12 10:58:16,663 Thread-1 8448 finished [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]14 2018-10-12 10:58:16,663 Thread-2 1064good job15

16 Process finished with exit code 0

View Code

总结:使用同一个Event实例的标记flag,谁wait 就是等到flag变为 True,或等到超时返回False,不限等待个数。

wait使用:

ContractedBlock.gif

ExpandedBlockStart.gif

1 from threading importEvent, Thread2 importlogging3 importtime4

5 FORMAT = '%(asctime)s %(threadName)s %(thread)d %(message)s'

6 logging.basicConfig(format=FORMAT, level=logging.INFO)7

8 defboss(event:Event):9 logging.info('boss')10 while event.wait(6):11 logging.info('good job')12 break

13

14

15 def worker(event:Event, count=10):16 logging.info('working')17 cups =[]18 whileTrue:19 logging.info('make 1')20 time.sleep(0.5)21 cups.append(1)22 if len(cups) >=count:23 event.set()24 break

25 logging.info('finished {}'.format(cups))26

27 event =Event()28 w = Thread(target=worker, args=(event,))29 b = Thread(target=boss, args=(event,))30 w.start()31 b.start()

View Code

Event练习:实现Timer,延时执行的线程,延时计add(x, y)

ContractedBlock.gif

ExpandedBlockStart.gif

1 from threading importThread, Event2

3 classTimer:4 def __init__(self, interval, fn, args=(), kwargs={}):5 self.interval =interval6 self.fn =fn7 self.args =args8 self.kwargs =kwargs9 self.event =Event()10

11 defstart(self):12 Thread(target=self.run).start()13

14 defcancel(self):15 self.event.set()16

17 defrun(self):18 self.event.wait(self.interval)19 if notself.event.is_set():20 print(self.args, self.kwargs)21 self.fn(*self.args, **self.kwargs)22 self.event.set()23 defadd(x, y):24 print(x +y)25

26 t = Timer(4, add,(4, 5) )27 print(t.args, t.kwargs)28 t.start()29 #t.cancel()

30

31 print('--------------------------------')32 print('main thread exit')33 add(5, 6)

test

结果:

ContractedBlock.gif

ExpandedBlockStart.gif

1 (4, 5) {}2 --------------------------------

3 main thread exit4 11

5 (4, 5) {}6 9

View Code

测试:cancel

ContractedBlock.gif

ExpandedBlockStart.gif

1 from threading importThread, Event2

3 classTimer:4 def __init__(self, interval, fn, args=(), kwargs={}):5 self.interval =interval6 self.fn =fn7 self.args =args8 self.kwargs =kwargs9 self.event =Event()10

11 defstart(self):12 Thread(target=self.run).start()13

14 defcancel(self):15 self.event.set()16

17 defrun(self):18 self.event.wait(self.interval)19 if notself.event.is_set():20 self.fn(*self.args, **self.kwargs)21 self.event.set() #习惯上 做完了,不允许在做一次了

22 #print(self.event.is_set())

23 defadd(x, y):24 print(x +y)25

26 t = Timer(2, add,(4, 5) )27 t.start()28 t.cancel()29

30 print('--------------------------------')31 print('main thread exit')32 add(5, 6)

View Code

结果:

ContractedBlock.gif

ExpandedBlockStart.gif

1 --------------------------------

2 main thread exit3 11

4

5 Process finished with exit code 0

View Code

3、Lock

锁,凡是存在共享资源争抢的地方都可以使用锁,从而保证只有一个使用这可以完全使用这个资源。

Lock,锁,一旦线程获得锁,其他试图获取锁的线程将被阻塞。

名称

含义

acquire(blocking=True, timeout=-1)

默认阻塞,阻塞可以设置超时时间,非阻塞时,timeout禁止设置,成功获取锁,返回True,否则返回Fasle

release()

释放锁,可以从任何线程调用释放,已上的锁,会被重置为unlock未上锁的锁上调用,抛RuntimeError异常

测试:需求:订单生产1000个杯子,组织10个工人生产。

1、非锁模式:

ContractedBlock.gif

ExpandedBlockStart.gif

1 importthreading2 from threading importThread , Lock3 importlogging4 importtime5

6 FORMAT = '%(asctime)s %(threadName)s %(thread)d %(message)s'

7 logging.basicConfig(format=FORMAT,level=logging.INFO)8

9 cups =[]10

11 def worker(count=10):12 logging.info("I'm workin")13 while len(cups)

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

<

ContractedBlock.gif

ExpandedBlockStart.gif

<

ContractedBlock.gif

ExpandedBlockStart.gif

<

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

1243334-20181015154234141-1675269132.png

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

1243334-20181015154100982-111320316.png

1243334-20181015154351438-2141631584.png

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

ContractedBlock.gif

ExpandedBlockStart.gif

1243334-20181015164825374-1618367813.png

1243334-20181015164833402-1474514377.png

1243334-20181015165251664-1646642043.png

1243334-20181015165714360-559791062.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值