多线程和线程的同步

一、线程同步的目的?
有一些特定的代码或者数据不希望被多个线程执行,比如:一个全局变量被多个线程同时做自增操作时,可能会造成逾期结果和实现结果不一致的问题。
二、线程同步的几种方法
线程同步有很多种方法,以下介绍三种方法:锁同步、信号量、Events事件。
三、锁同步

1、基本原理

锁是Python的threading模块提供的最基本的同步机制。在任一时刻,一个锁对象可能被一个线程获取,或者不被任何线程获取。如果一个线程尝试去获取一个已经被另一个线程获取到的锁对象,那么这个想要获取锁对象的线程只能暂时终止执行直到锁对象被另一个线程释放掉。
锁通常被用来实现对共享资源的同步访问。为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问完后,再调用release方法释放锁:

lock = Lock()
 
lock.acquire() #: will block if lock is already held
#对共享资源进行操作
lock.release()

四、信号量(Semaphore)

1、基本原理

信号量是一个更高级的锁机制。信号量内部有一个计数器而不像锁对象内部有锁标识,而且只有当占用信号量的线程数超过信号量时线程才阻塞。这允许了多个线程可以同时访问相同的代码区。

semaphore = threading.BoundedSemaphore()
semaphore.acquire() #: counter减小
#对共享资源进行操作
semaphore.release() #: counter增大
当信号量被获取的时候,计数器减小;当信号量被释放的时候,计数器增大。当获取信号量的时候,如果计数器值为0,则该进程将阻塞。当某一信号量被释放,counter值增加为1时,被阻塞的线程(如果有的话)中会有一个得以继续运行。

五、Events事件

1、基本原理

一个事件是一个简单的同步对象,事件表示为一个内部标识(internal flag),线程等待这个标识被其它线程设定,或者自己设定、清除这个标识。

event = threading.Event()
 
#: 一个客户端线程等待flag被设定
event.wait()
 
#: 服务端线程设置或者清除flag
event.set()
event.clear()

一旦标识被设定,wait方法就不做任何处理(不会阻塞);当标识被清除时,wait方法将被阻塞直至其被重新设定。任意数量的线程可能会等待同一个事件。

2、代码举例

我们以红绿灯为例,灯(light)和车(car)为两根线程,我们可以根据绿灯是否被设置作为事件,对上述两个线程进行同步。

(1)light线程和car线程的同步关系

事件:绿灯是否被设置;绿灯如果被设置(set),car事件来到的时候不会阻塞,car可以执行;绿灯如果被清除(clear),car事件来到的时候(代表红灯)会阻塞,car线程不能执行。

light线程负责对标志位进行设置或者清除,car线程负责检查标志位,并根据具体的情况判断是红灯还是绿灯。

(2)代码实现

import time,threading

#创建一个event
event = threading.Event()

def light():
    count = 0 #计数器,显示红绿灯的秒数
    event.set()
    while True:
        if count>5 and count<10: #进入红灯的时间,清除绿灯的标志位,wait()方法之后进入等待
            event.clear()
            print('\033[41;1mred light is on ...\033[0m')
        elif count>10:
            event.set()
            count = 0
        else:
            print('\033[42;1mgreen light is on ...\033[0m')
        time.sleep(1)
        count += 1

def car(name):
    while True:
        if event.is_set(): #绿灯标志位被设置,代表绿灯
            print('[%s] running ...' % name)
            time.sleep(1)
        else: #代表红灯
            print('[%s] is wait the ligth to change...' % name)
            event.wait()
            print('\033[34;1m[%s] green light is on, starting going now \033[0m' % name)

light_th = threading.Thread(target=light)
light_th.start()

car_th = threading.Thread(target=car, args=('大众',))
car_th.start()







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值