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

执行结果:

原文地址:https://www.cnblogs.com/yunxintryyoubest/p/14166001.html