加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python--线程同步原语

发布时间:2020-12-17 00:16:09 所属栏目:Python 来源:网络整理
导读:Threading模块是python3里面的多线程模块,模块内集成了许多的类,其中包括Thread,Condition,Event,Lock,Rlock,Semaphore,Timer等等。下面这篇文章主要通过案例来说明其中的Event和Segmaphore(Boundedsegmaphore)的使用。关于Lock的使用可以移步到我

Threading模块是python3里面的多线程模块,模块内集成了许多的类,其中包括Thread,Condition,Event,Lock,Rlock,Semaphore,Timer等等。下面这篇文章主要通过案例来说明其中的Event和Segmaphore(Boundedsegmaphore)的使用。关于Lock的使用可以移步到我之前写的文章

Event

Event类内部保存着一个flags参数,标志事件的等待与否。

Event类实例函数

1. set() 将flags设置为True,事件停止阻塞

2. clear()? 将flags重新设置为False,删除flags,事件重新阻塞

3. wait() 将事件设置为等待状态

4.

(1)单个事件等待其他事件的发生

?

time =<span style="color: #0000ff">def<span style="color: #000000"> event_wait():
<span style="color: #0000ff">print
<span style="color: #000000">(ctime())
event.wait()
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">这是event_wait方法中的时间<span style="color: #800000">'<span style="color: #000000">,ctime())

<span style="color: #0000ff">def<span style="color: #000000"> event_set(n):
sleep(n)
event.set()
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">这是event_set方法中的时间<span style="color: #800000">'<span style="color: #000000">,ctime())

thread1 = Thread(target=<span style="color: #000000">event_wait)
thread2 = Thread(target=event_set,args=(3<span style="color: #000000">,))

thread1.start()
thread2.start()

结果:

Sat Nov 17 10:01:05 201817 10:01:08 201817 10:01:08 2018

(2)多个事件先后发生

下面以赛跑来作为例子。假设5条跑道上,每条跑道各有一名运动员,分别为ABCDE。

具体代码:

threading threading event =<span style="color: #000000"> Event()

<span style="color: #0000ff">def<span style="color: #000000"> do_wait(athlete):
racetrack =<span style="color: #000000"> threading.current_thread().getName()
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">%s准备就绪<span style="color: #800000">' %<span style="color: #000000"> racetrack)
event.wait()
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">%s听到枪声,起跑!<span style="color: #800000">'%<span style="color: #000000">athlete)

thread1 = Thread(target=do_wait,args=(<span style="color: #800000">"<span style="color: #800000">A<span style="color: #800000">"<span style="color: #000000">,))
thread2 = Thread(target=do_wait,args=(<span style="color: #800000">"<span style="color: #800000">B<span style="color: #800000">"<span style="color: #000000">,))
thread3 = Thread(target=do_wait,args=(<span style="color: #800000">"<span style="color: #800000">C<span style="color: #800000">"<span style="color: #000000">,))
thread4 = Thread(target=do_wait,args=(<span style="color: #800000">"<span style="color: #800000">D<span style="color: #800000">"<span style="color: #000000">,))
thread5 = Thread(target=do_wait,args=(<span style="color: #800000">"<span style="color: #800000">E<span style="color: #800000">"<span style="color: #000000">,))

threads =<span style="color: #000000"> []
threads.append(thread1)
threads.append(thread2)
threads.append(thread3)
threads.append(thread4)
threads.append(thread5)

<span style="color: #0000ff">for th <span style="color: #0000ff">in<span style="color: #000000"> threads:
th.start()

event.set() <span style="color: #008000">#<span style="color: #008000">这个set()方法很关键,同时对5个线程中的event进行set操作

结果:

Thread-----

可以看出多个线程中event的set()是随机的,其内部的实现是因为一个notify_all()方法。这个方法会一次性释放所有锁住的事件,哪个线程先抢到线程运行的时间片,就先释放锁。

之所以能够只调用一个set()函数就可以实现所有event的退出阻塞,是因为event.wait()是在线程内部实现的,而set()函数是在进程中调用,python多线程共享一个进程内存空间。如果是在不同进程中调用这两个函数则无法实现。

BoundedSegmaphore

如果在主机执行IO密集型任务的时候再执行这种短时间内完成大量任务(多线程)的程序时,计算机就有很大可能会宕机。

这时候就可以为这段程序添加一个计数器(counter)功能,来限制一个时间点内的线程数量。当每次进行IO操作时,都需要向segmaphore请求资源(锁),如果没有请求到,就阻塞等待,请求成功才就像执行任务。

BoundedSegmaphore和Segmaphore的区别

BoundedSegmaphore请求的锁数量固定为传入参数,而Segmaphore请求的锁数量可以超过传入的参数。

主要函数:

1. acquire()? 请求锁

2. release()?? 释放锁

下面以一个租房的例子来说明这种固定锁数量的机制。假设一家小公寓有6间房,原本有2个住户在住着。

具体代码实现:

threading time random lock =<span style="color: #000000"> Lock()
num
= 6<span style="color: #000000">
hotel
=<span style="color: #000000"> BoundedSemaphore(num)

<span style="color: #0000ff">def<span style="color: #000000"> logout():
lock.acquire()
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">I want to logout<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">A customer logout...<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">try<span style="color: #000000">:
hotel.release()
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">Welcome again<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">except<span style="color: #000000"> ValueError:
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">Sorry,wait a moment.<span style="color: #800000">'<span style="color: #000000">)
lock.release()

<span style="color: #0000ff">def<span style="color: #000000"> login():
lock.acquire()
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">I want to login<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">A customer login...<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">if<span style="color: #000000"> hotel.acquire(False):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">Ok,your room number is...<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">else<span style="color: #000000">:
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">Sorry,our hotel is full<span style="color: #800000">'<span style="color: #000000">)
lock.release()

<span style="color: #008000">#<span style="color: #008000">房东
<span style="color: #0000ff">def<span style="color: #000000"> producer(loops):
<span style="color: #0000ff">for i <span style="color: #0000ff">in<span style="color: #000000"> range(loops):
logout()
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">还剩%s<span style="color: #800000">' % hotel._value,<span style="color: #800000">'<span style="color: #800000">房间<span style="color: #800000">'<span style="color: #000000">)
sleep(randrange(2<span style="color: #000000">))
<span style="color: #008000">#<span style="color: #008000">租客
<span style="color: #0000ff">def<span style="color: #000000"> consumer(loops):
<span style="color: #0000ff">for i <span style="color: #0000ff">in<span style="color: #000000"> range(loops):
login()
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">还剩%s<span style="color: #800000">' % hotel._value,<span style="color: #800000">'<span style="color: #800000">房间<span style="color: #800000">'<span style="color: #000000">)
sleep(randrange(2<span style="color: #000000">))
def main():
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">Start<span style="color: #800000">'<span style="color: #000000">)
room_num =<span style="color: #000000"> hotel._value
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">The hotel is full with %s room<span style="color: #800000">'%<span style="color: #000000">room_num)
<span style="color: #008000">#<span style="color: #008000">原本有2个住户
<span style="color: #000000">hotel.acquire()
hotel.acquire()
thread1 = Thread(target=producer,args=(randrange(2,8<span style="color: #000000">),))
thread2 = Thread(target=consumer,))
thread1.start()
thread2.start()

<span style="color: #0000ff">if <span style="color: #800080">name == <span style="color: #800000">'<span style="color: #800000">main<span style="color: #800000">'<span style="color: #000000">:
main()

结果:

The hotel full with 6

可以看出,房间数目永远不会超过6,因为_value值(BoundedSegmaphore内部的计数器counter)一定是传入的参数6。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读