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()

    执行结果:

  • 相关阅读:
    68
    56
    Django manager 命令笔记
    Django 执行 manage 命令方式
    Django 连接 Mysql (8.0.16) 失败
    Python django 安装 mysqlclient 失败
    H.264 SODB RBSP EBSP的区别
    FFmpeg—— Bitstream Filters 作用
    MySQL 远程连接问题 (Windows Server)
    MySQL 笔记
  • 原文地址:https://www.cnblogs.com/yunxintryyoubest/p/14166001.html
Copyright © 2011-2022 走看看