zoukankan      html  css  js  c++  java
  • python lock, semaphore, event实现线程同步

    lock 机制不管你是java, C#, 还是python都是常用的线程同步机制, 相比较C# 的锁机制, python的加锁显得比较简单, 直接调用threading 标准库的lock 就可以了. python 的 lock类有两个函数, 分别是acquire 函数以及 release 函数, 前者起到锁定的作用, 将状态设置为锁定状态, 后者则是解锁, 将状态设置为未锁定状态. 我们看看代码:

    # python 多线程同步  lock
    import threading
    from time import sleep
    
    
    num = 0
    lock = threading.Lock()
    
    
    def func(st):
        global num
        print(threading.currentThread().getName() + ' try to acquire the lock')
        if lock.acquire():  # 将状态修改为locked
            print(threading.currentThread().getName() + ' acquire the lock.')
            print(threading.currentThread().getName() + " :%s" % str(num))
            num += 1
            # sleep(st)
            print(threading.currentThread().getName() + ' release the lock.')
            lock.release()  # 将状态修改为unlocked
    
    
    t1 = threading.Thread(target=func, args=(8,))
    t2 = threading.Thread(target=func, args=(4,))
    t3 = threading.Thread(target=func, args=(2,))
    t1.start()
    t2.start()
    t3.start()

    我们开了三个线程去调用同一个func 函数, 由于线程的不确定性, 如果没有加锁, 此时运行的话就会很混乱, 三个线程去执行同一个函数, 如果涉及到了变量的数据变化更是坑!因此我们加了锁, 确保数据的正确性, 函数执行的顺序性!

    semaphore 信号量机制在python 里面也很简单就能够实现线程的同步。如果对操作系统有一定的了解, 那么对操作系统的PV原语操作应该有印象, 信号量其实就是基于这个机制的.semaphore 类是threading 模块下的一个类, 主要两个函数: acquire 函数, release 函数这和lock 类的函数是一样的, 只不过功能不一样, semaphore 机制的acquire 函数的参数允许你自己设置最大的并发量, 就是说允许多少个线程来操作同一个函数或是变量, 同时执行一次就会递减一次, release 函数则是递增, 如果计数到了0, 则阻塞起线程, 不再允许线程访问该方法或是变量.

    # python 多线程同步   semaphore
    import threading
    
    
    # 初始化信号量数量...当调用acquire 将数量置为 0, 将阻塞线程等待其他线程调用release() 函数
    semaphore = threading.Semaphore(2)
    
    
    def func():
        if semaphore.acquire():
            for i in range(5):
                print(threading.currentThread().getName() + ' get semaphore')
            semaphore.release()
            print(threading.currentThread().getName() + ' release semaphore')
    
    
    if __name__ == '__main__':
        for i in range(4):
            t1 = threading.Thread(target=func)
            t1.start()

    我们一次允许两个线程同时执行函数, 这可以从截图看出来:

    event 机制不仅能够实现线程间的通信, 也是实现线程同步的一个好方法。事件是线程之间通信的最简单的机制之一, 一个线程指示一个事件和其他线程等待它.
    event.py 是threading 模块下的一个类, 相比较前面两个机制, 这个类提供了四个方法, 分别是 is_set() 函数, set() 函数, clear() 函数, wait() 函数.
    is_set判断事件管理标志是不是为true, 只有为true时, 才会返回
    set 将标志设置为true
    clear 将标志设置为flase
    wait 等到标志为true时, 才会停止阻塞线程

    import logging
    import threading
    import time
    
    
    # 打印线程名以及日志信息
    logging.basicConfig(level=logging.DEBUG, format="(%(threadName)-10s : %(message)s", )
    
    
    def wait_for_event_timeout(e, t):
        """Wait t seconds and then timeout"""
        while not e.isSet():
            logging.debug("wait_for_event_timeout starting")
            event_is_set = e.wait(t)  # 阻塞, 等待设置为true
            logging.debug("event set: %s" % event_is_set)
            if event_is_set:
                logging.debug("processing event")
            else:
                logging.debug("doing other work")
    
    
    e = threading.Event()  # 初始化为false
    t2 = threading.Thread(name="nonblock", target=wait_for_event_timeout, args=(e, 2))
    t2.start()
    logging.debug("Waiting before calling Event.set()")
    # time.sleep(7)
    e.set()  # 唤醒线程, 同时将event 设置为true
    logging.debug("Event is set")
  • 相关阅读:
    VS2008找不到MFC90d.dll错误解决方法
    字符编码之间的转换
    java 中使用RSA非对称性加密解密
    java eclipse中使用wsdl生成soap 的客户端代码
    java 打印空心菱形的两种实现
    Chrome 快捷键
    电脑常用快捷键
    VS2013常用快捷键
    Eclipse常用快捷键
    java 使用for循环打印杨辉三角形
  • 原文地址:https://www.cnblogs.com/zhiyong-ITNote/p/7598887.html
Copyright © 2011-2022 走看看