zoukankan      html  css  js  c++  java
  • Python-锁

    一. Python线程互斥锁Lock

    使用多线程可以同时执行多个任务,提高开发效率,但是在实际开发中往往我们会碰到线程同步问题,假如有这样一个场景:对全局变量累加1000000此,为了提高开发效率,我们可以使用多线程完成,示例代码如下:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    # 导入线程threading模块
    import threading
    
    # 声明全局变量
    g_num = 0
    
    
    def my_thread1():
        # 声明全局变量
        global g_num
        # 循环 1000000 次,每次累计加 1
        for i in range(0, 1000000):
            g_num = g_num + 1
    
    
    def my_thread2():
        # 声明全局变量
        global g_num
        # 循环 1000000 次,每次累计加 1
        for i in range(0, 1000000):
            g_num = g_num + 1
    
    
    def main():
        # 声明全局变量
        global g_num
        # 初始化全局变量,初始值为 0
        # 创建两个线程,对全局变量进行累计加 1
        t1 = threading.Thread(target=my_thread1)
        t2 = threading.Thread(target=my_thread2)
    
        # 启动线程
        t1.start()
        t2.start()
        # 阻塞函数,等待线程结束
        t1.join()
        t2.join()
        # 获取全局变量的值
        print("计算结果:%d " % (g_num))
    
    
    if __name__ == "__main__":
        main()

    执行结果:

     这个是什么操作?看着代码好像也没问题,两个线程,各自累加1000000次,不应该输出的是2000000吗?

    1. 线程共享全局变量

    分析上面的代码:两个线程共享全局变量并执行for循环1000000,每次自动加1,我们都知道两个线程都是在同时运行,也就是说两个线程同时在执行g_num = g-num = 1操作,经过我们冷静分析一波,貌似结果该是应该等于2000000,对不对?

    首先我们将上面的全局变量自动加1的代码分为两步:

    第一步: g_num + 1

    第二步: 将g_num + 1的结果赋值给g_num

    由此可见,执行一个完整的自动加1的过程需要两步,然而线程确是同时在运行,谁也不能保证线程1的第一步和第二部执行完成之后才执行线程2的第一步和第二步,执行的过程充满随机性,这就是导致每次计算结果不同的原因所在。

    2. 线程互斥锁

    为了避免上面的问题,我们可以利用线程互斥锁解决这个问题,那么线程互斥锁到底是个什么原理呢?互斥锁就好比排队上厕所,一个坑位只能蹲一个人,只有占用坑位的人完事了,另一个人才能上!!

     创建互斥锁

    导入线程模块,通过threading.Lock()创建互斥锁

    import threading
    mutex = threading.Lock()

    锁定资源/解锁资源

    acquire() --锁定资源,此时资源是锁定状态,其他线程无法修改锁定的资源,知道等待锁定的资源释放之后才能操作

    release() --释放资源,也成为解锁操作,对锁定的资源解锁,解锁之后其他线程可以对资源正常操作

    上面的代码为例子:想得到正确的结果,可以直接利用互斥锁在全局变量加1之前锁定资源,然后在计算完成之后释放资源,这样就是一个完整的计算过程,至于应该是那个线程先执行,无所谓,先到先得,凭本事说话

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    # 导入线程threading模块
    import threading
    mutex = threading.Lock()
    
    # 声明全局变量
    g_num = 0
    
    def my_thread1():
        # 声明全局变量
        global g_num
        # 循环 1000000 次,每次累计加 1
        for i in range(0, 1000000):
            mutex.acquire()
            g_num = g_num + 1
            mutex.release()
    
    
    def my_thread2():
        # 声明全局变量
        global g_num
        # 循环 1000000 次,每次累计加 1
        for i in range(0, 1000000):
            mutex.acquire()
            g_num = g_num + 1
            mutex.release()
    
    def main():
        # 声明全局变量
        global g_num
        # 初始化全局变量,初始值为 0
        # 创建两个线程,对全局变量进行累计加 1
        t1 = threading.Thread(target=my_thread1)
        t2 = threading.Thread(target=my_thread2)
    
        # 启动线程
        t1.start()
        t2.start()
        # 阻塞函数,等待线程结束
        t1.join()
        t2.join()
        # 获取全局变量的值
        print("计算结果:%d " % (g_num))
    
    
    if __name__ == "__main__":
        main()

    执行结果:

  • 相关阅读:
    Spring-----<context:annotation-config/>
    Spring-----代码中使用注入的Properties配置属性
    Spring-----事务配置的五种方式
    读书汇总贴
    读书_2019年
    有道词典_每日一句_2019/08
    微信小程序 报错Failed to load image
    有道词典_每日一句_2019/07
    微信小程序 base64格式图片的显示及保存
    Mac版微信无法安装之始末
  • 原文地址:https://www.cnblogs.com/yunxintryyoubest/p/14166001.html
Copyright © 2011-2022 走看看