python中的GIL锁与线程互斥锁的区别

陌路散爱 提交于 2019-12-02 15:08:59

python中的GIL锁与线程互斥锁的区别

GIL锁:
GIL的全称是Global Interpreter Lock(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定。某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行。GIL只在cpython中才有。

互斥锁
那么多线程编程时通过调用threading模块的Lock函数,来获取一把互斥锁。
互斥锁就是对共享数据进行锁定,保证同一时刻只有一个线程操作数据。

GIL锁的释放
在python3.x中,GIL不使用ticks计数,改为使用计时器(执行时间达到阈值后,当前线程释放GIL),这样对CPU密集型程序更加友好,但依然没有解决GIL导致的同一时间只能执行一个线程的问题,所以效率依然不尽如人意。

那么下来用代码来解释互斥锁与GIL锁的区别

假设有这样一个场景:

import threading

# 定义全局变量
g_num = 0
# 循环一次给全局变量加1
def sum_num1():
    for i in range(1000000):
        global g_num
        g_num += 1

    print("sum1:", g_num)

# 循环一次给全局变量加1
def sum_num2():
    for i in range(1000000):
        global g_num
        g_num += 1
    print("sum2:", g_num)
if __name__ == '__main__':
    # 创建两个线程
    A = threading.Thread(target=sum_num1)
    B = threading.Thread(target=sum_num2)

    # 启动线程
    A.start()
    # 启动线程
    B.start()

当A线程拿到GIL锁,有了执行权限后,对全局变量g_num进行数据操作,当GIL锁的计时器执行时间达到阈值,释放GIL锁让别的线程执行,B线程拿到GIL锁后同样对g_num进行数据操作,当A线程再次拿到GIL锁时就会出现和上一次操作的数据结果不一致,此时就出现了资源抢夺,数据操作不安全,因此我们要自己手动对线程加锁。就算A线程拿到了GIL锁有了执行权限,那么如果他拿不到我们加的锁,就没有权限对数据进行操作,这样就保证了数据的安全。

总结

GIL锁是解释器级别的锁,保证同一时刻进程中只有一个线程拿到GIL锁,拥有执行权限。而线程互斥锁是保证同一时刻只有一个线程能对数据进行操作,是数据级别的锁。

仅为个人理解,欢迎大神指正。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!