python面试题——什么是GIL ;什么时候释放GIL锁;互斥锁(同步锁)和GIL的区别

导读:本篇文章讲解 python面试题——什么是GIL ;什么时候释放GIL锁;互斥锁(同步锁)和GIL的区别,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

在这里插入图片描述

一、什么是GIL

GIL 是python的全局解释器锁,同一进程中假如有多个线程运行,一个线程在运行python程序的时候会霸占python解释器(加了一把锁即GIL),使该进程内的其他线程无法运行,等该线程运行完后其他线程才能运行。如果线程运行过程中遇到耗时操作,则解释器锁解开,使其他线程运行。所以在多线程中,线程的运行仍是有先后顺序的,并不是同时进行。

我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行。GIL只在cpython中才有。

二、什么时候释放GIL锁

1、某个线程运行完后其他线程才能运行。
2、如果线程运行过程中遇到耗时操作,则解释器锁解开,使其他线程运行。

三、互斥锁(同步锁)和GIL的区别

1、举例:多线程执行任务造成数据混乱的问题

import threading

g_num=0
def run():
    global g_num

    for i in range(1000000):
        g_num+=1
    print(f'当前线程{threading.current_thread().name}的执行结果:',g_num)


if __name__ == '__main__':
    thread=[]
    for i in range(10):
        t=threading.Thread(target=run)
        t.start()
        thread.append(t)

    for t in thread:
        t.join()
    print('主线程执行完毕')

执行结果:很明显数据已经混乱了

当前线程Thread-1的执行结果: 1000000
当前线程Thread-2的执行结果:当前线程Thread-3的执行结果: 1581377
 当前线程Thread-4的执行结果:2690126
 当前线程Thread-5的执行结果: 35138763690126

当前线程Thread-6的执行结果: 当前线程Thread-7的执行结果: 5545936
4690126
当前线程Thread-8的执行结果:当前线程Thread-9的执行结果:  6244936
当前线程Thread-10的执行结果: 82094017209401

主线程执行完毕

Process finished with exit code 0

2、数据混乱的原因:

cpu分成多个时间片段,启动10线程,分配10个cpu时间片段,当我累加数字设置比较小的时候,在单个cpu时间片段内,for循环代码就执行完,就不会产生数据混乱的。当我数据设置的比较大时,在单个cpu时间片段内,for循环代码就执行不完,并且没有分配2个或2个以上的连续的cpu时间片段,导致一个cpu时间片段没有执行完该线程,下一个线程开始执行了

问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期。这种现象称为”线程不安全””。

3、解决数据混乱(同步锁、互斥锁)

lock=Lock():创建同步锁
lock.acquire():获得这把锁的钥匙
lock.release():释放锁;如果不释放锁,其他的线程拿不到锁,是不会运行的;
释放锁后其他线程会抢这把锁。谁先抢到这把锁不一定
必须使用同一把锁

import threading


g_num=0
def run():
    global g_num

    lock.acquire()
    for i in range(1000000):
        g_num+=1
    print(f'当前线程{threading.current_thread().name}的执行结果:',g_num)
    lock.release()

if __name__ == '__main__':
    lock=threading.Lock()
    thread=[]
    for i in range(10):
        t=threading.Thread(target=run)
        t.start()
        thread.append(t)

    for t in thread:
        t.join()
    print('主线程执行完毕')

执行结果:

当前线程Thread-1的执行结果: 1000000
当前线程Thread-2的执行结果: 2000000
当前线程Thread-3的执行结果: 3000000
当前线程Thread-4的执行结果: 4000000
当前线程Thread-5的执行结果: 5000000
当前线程Thread-6的执行结果: 6000000
当前线程Thread-7的执行结果: 7000000
当前线程Thread-8的执行结果: 8000000
当前线程Thread-9的执行结果: 9000000
当前线程Thread-10的执行结果: 10000000
主线程执行完毕

四、总结:

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

GIL锁是解释器级别的锁,保证同一时刻进程中只有一个线程拿到GIL锁,拥有执行权限。
在这里插入图片描述

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/73989.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!