zoukankan      html  css  js  c++  java
  • Python 线程同步锁, 信号量

    同步锁

    import  time, threading
    
    def addNum():
        global num
        num -= 1
    
    num = 100
    
    thread_list = []
    for i in range(100):
        t = threading.Thread(target=addNum)
        t.start()
        thread_list.append(t)
    
    for t in thread_list:
        t.join()
    
    print('final num:', num)
    
    运行结果:
    final num: 0
    
    import  time, threading
    
    def addNum():
        global num
        #num -= 1
        tmp = num
        time.sleep(0.00001)
        num = tmp - 1
    
    num = 100
    
    thread_list = []
    for i in range(100):
        t = threading.Thread(target=addNum)
        t.start()
        thread_list.append(t)
    
    for t in thread_list:
        t.join()
    
    print('final num:', num)
    
    运行结果:
    final num: 93 
    或
    final num: 91
    或
    final num: 94
    

    原因:
    第一个程序中,num -= 1 这种写法,程序执行动作太快(完成这个动作在 cup 切换的时间内)
    第二个程序中,把 num -= 1 , 加入了 sleep 时间,100个线程存在没有执行完就进行了切换,导致全局的 num 没有正常返回。引用下大神的图发现总结得非常好:

    在上面的例子中 使用 join 方法会把整个线程停住,造成了串行,失去了多线程的意义,我们只需要在涉及到计算公共数据的时候串行执行即可。

    使用同步锁处理计算公共的数据

    import  time, threading
    
    def addNum():
        global num
    
        lock.acquire()
        tmp = num
        time.sleep(0.00001)
        num = tmp - 1
        lock.release()
    
    
    num = 100
    lock = threading.Lock()
    thread_list = []
    for i in range(100):
        t = threading.Thread(target=addNum)
        t.start()
        thread_list.append(t)
    
    for t in thread_list:
        t.join()
    
    print('final num:', num)
    
    运算结果:
    final num: 0
    

    线程死锁和递归锁

    import  threading, time
    
    class myThread(threading.Thread):
        def doA(self):
            lockA.acquire()
            print(self.name, "gotlockA", time.ctime())
            time.sleep(3)
            lockB.acquire()
            print(self.name, "gotlockB", time.ctime())
            lockB.release()
            lockA.release()
    
        def doB(self):
            lockB.acquire()
            print(self.name, "gotlockB", time.ctime())
            time.sleep(2)
            lockA.acquire()
            print(self.name, "gotlockA", time.ctime())
            lockA.release()
            lockB.release()
    
        def run(self):
            self.doA()
            self.doB()
    
    if __name__ == '__main__':
        lockA = threading.Lock()
        lockB = threading.Lock()
        threads = []
        for i in range(5):
            threads.append(myThread())
        for t in threads:
            t.start()
        for t in threads:
            t.join()
    
    #运行结果:
    Thread-1 gotlockA Sat Jul 28 15:09:31 2018
    Thread-1 gotlockB Sat Jul 28 15:09:34 2018
    Thread-1 gotlockB Sat Jul 28 15:09:34 2018
    Thread-2 gotlockA Sat Jul 28 15:09:34 2018
    
    

    使用递归锁

    import  threading, time
    
    class myThread(threading.Thread):
        def doA(self):
            lock.acquire()
            print(self.name, "gotlockA", time.ctime())
            time.sleep(3)
            lock.acquire()
            print(self.name, "gotlockB", time.ctime())
            lock.release()
            lock.release()
    
        def doB(self):
            lock.acquire()
            print(self.name, "gotlockB", time.ctime())
            time.sleep(2)
            lock.acquire()
            print(self.name, "gotlockA", time.ctime())
            lock.release()
            lock.release()
    
        def run(self):
            self.doA()
            self.doB()
    
    if __name__ == '__main__':
        lock = threading.RLock()
        threads = []
        for i in range(5):
            threads.append(myThread())
        for t in threads:
            t.start()
        for t in threads:
            t.join()
    
    运行结果:
    Thread-1 gotlockA Sat Jul 28 15:19:35 2018
    Thread-1 gotlockB Sat Jul 28 15:19:38 2018
    Thread-1 gotlockB Sat Jul 28 15:19:38 2018
    Thread-1 gotlockA Sat Jul 28 15:19:40 2018
    Thread-3 gotlockA Sat Jul 28 15:19:40 2018
    Thread-3 gotlockB Sat Jul 28 15:19:43 2018
    Thread-3 gotlockB Sat Jul 28 15:19:43 2018
    Thread-3 gotlockA Sat Jul 28 15:19:45 2018
    Thread-5 gotlockA Sat Jul 28 15:19:45 2018
    Thread-5 gotlockB Sat Jul 28 15:19:48 2018
    Thread-5 gotlockB Sat Jul 28 15:19:48 2018
    Thread-5 gotlockA Sat Jul 28 15:19:50 2018
    Thread-4 gotlockA Sat Jul 28 15:19:50 2018
    Thread-4 gotlockB Sat Jul 28 15:19:53 2018
    Thread-4 gotlockB Sat Jul 28 15:19:53 2018
    Thread-4 gotlockA Sat Jul 28 15:19:55 2018
    Thread-2 gotlockA Sat Jul 28 15:19:55 2018
    Thread-2 gotlockB Sat Jul 28 15:19:58 2018
    Thread-2 gotlockB Sat Jul 28 15:19:58 2018
    Thread-2 gotlockA Sat Jul 28 15:20:00 2018
    

    信号量

    信号量用来控制线程并发数的,BoundedSemaphore或Semaphore管理一个内置的计数 器,每当调用acquire()时-1,调用release()时+1,计数器不能小于0,当计数器为 0时,acquire()将阻塞线程至同步锁定状态,直到其他线程调用release()。(类似于停车位的概念)。
    BoundedSemaphore与Semaphore的唯一区别在于前者将在调用release()时检查计数 器的值是否超过了计数器的初始值,如果超过了将抛出一个异常。

    import threading, time
    
    class myThread(threading.Thread):
        def run(self):
            if semaphore.acquire():
                print(self.name)
                time.sleep(5)
                semaphore.release()
    
    if __name__ == "__main__":
        semaphore = threading.Semaphore(5)
        thrs = []
        for i in range(20):
            thrs.append(myThread())
        for t in thrs:
            t.start()
    
    #运行结果:
    Thread-1
    Thread-2
    Thread-3
    Thread-4
    Thread-5
    Thread-6
    Thread-7
    Thread-9
    Thread-10
    Thread-8
    Thread-11
    Thread-13
    Thread-14
    Thread-12
    Thread-15
    Thread-18
    Thread-16
    Thread-17
    Thread-19
    Thread-20
    
    import threading, time
    
    class myThread(threading.Thread):
        def run(self):
            if semaphore.acquire():
                print(self.name)
                time.sleep(5)
                semaphore.release()
    
    if __name__ == "__main__":
        semaphore = threading.BoundedSemaphore(5)
        thrs = []
        for i in range(20):
            thrs.append(myThread())
        for t in thrs:
            t.start()
    
    #运行结果:
    Thread-1
    Thread-2
    Thread-3
    Thread-4
    Thread-5
    Thread-6
    Thread-8
    Thread-10
    Thread-9
    Thread-7
    Thread-12
    Thread-14
    Thread-15
    Thread-13
    Thread-11
    Thread-16
    Thread-17
    Thread-20
    Thread-19
    Thread-18
    
  • 相关阅读:
    .Net转Java自学之路—SpringMVC框架篇九(拦截器)
    .Net转Java自学之路—SpringMVC框架篇八(RESTful支持)
    移动端高清适配、布局开发解决方案
    Webpack+Gulp+React+ES6开发
    gulp使用gulp-file-include将header/footer引入页面
    git在window与linux的换行符问题
    文件(图片)上传组件
    ie8、9跨域上传文件(图片)
    移动端rem布局背景图片使用以及sprite雪碧图
    iOS/Android 浏览器(h5)及微信中唤起本地APP
  • 原文地址:https://www.cnblogs.com/klvchen/p/9381511.html
Copyright © 2011-2022 走看看