zoukankan      html  css  js  c++  java
  • 线程,线程安全与python的GIL锁

    在看的过程中,接触到一个名词,一个从学python开始就一直看到,但是从来都是一知半解的名词,心里不开心,必须把它搞明白,对了,这个词就是 GIL。网上搜索了一些资料,粗浅的理解了什么是GIL,自己感觉学习的过程比较好,感觉略有收获,老规矩,为了巩固知识,自己整片文章出来写一写,其实好多文章已经写的很完善了,所以这篇随笔,只做知识巩固,如有雷同,请各位原创作者原谅,小菜鸟一枚,如果哪里写的有问题,还请各位前辈不吝指正。

      一句话:解决多线程之间数据完整性和状态同步的最简单方法自然就是加锁。

      首先,GIL的全名,Global Interpreter Lock,鉴于英文水平,不做名词翻译,以免误导。大体解释一下,这个锁就是用来为了解决Cpython多线程中线程不安全问题引入的一个全局排它锁,它的作用就是在多线程情况下,保护共享资源,为了不让多个线程同时操作共享资源,导致不可预期的结果而加上的锁,在一个线程操作共享资源时,其他线程请求该资源,只能等待GIL解锁。这个设置在Cpython刚引入多线程概念的时候就有了,然后后续的各种包和组件开发都不可避免的受到了GIL的影响,所以有人会说,python在多线程处理的时候很慢。python GIL实现方式类似于如下伪代码:

    if __name__ == '__main__':
        GIL锁开始运作
        主线程做操作
        主线程完成操作
        GIL锁释放资源

    所以多线程共同操作共享资源的时候,有一个线程竞得了资源,它就被GIL锁保护起来,其他线程只能是在那里等着,但是这个时候,线程的休眠唤醒,全部会消耗CPU资源,所以嘞,就会慢。

      看到这个时候,我又发现了一个名词:线程安全。这个名词,也是那种特别熟悉,但就是无法清晰的说出它是啥的概念。查了资料,在这记一下:

      线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。

      我自己想了一下,大约就是这样,比如整个列表,俩个线程同时在列表中append操作,如果没有锁的保护,在机缘巧合之下,俩个线程同时先后申请了空间且没来得及插入数据,然后这时列表中只会有一个空间,那么在插入过程中只能有一个数据写入,会造成不可知后果,有可能报错终止,有可能有一个线程操作没成功,那么这个就是线程不安全了,大白话说,只要线程之间没有共享资源,那么就是线程安全的,有共享资源,为了保证线程安全,需要引进锁的机制。

      而后的文章中,有前辈做过实验:

    顺序执行的单线程(single_thread.py)
    
    #! /usr/bin/python
    
    from threading import Thread
    import time
    
    def my_counter():
        i = 0
        for _ in range(100000000):
            i = i + 1
        return True
    
    def main():
        thread_array = {}
        start_time = time.time()
        for tid in range(2):
            t = Thread(target=my_counter)
            t.start()
            t.join()
        end_time = time.time()
        print("Total time: {}".format(end_time - start_time))
    
    if __name__ == '__main__':
        main()
    同时执行的两个并发线程(multi_thread.py)
    
    #! /usr/bin/python
    
    from threading import Thread
    import time
    
    def my_counter():
        i = 0
        for _ in range(100000000):
            i = i + 1
        return True
    
    def main():
        thread_array = {}
        start_time = time.time()
        for tid in range(2):
            t = Thread(target=my_counter)
            t.start()
            thread_array[tid] = t
        for i in range(2):
            thread_array[i].join()
        end_time = time.time()
        print("Total time: {}".format(end_time - start_time))
    
    if __name__ == '__main__':
        main()

    最终结果如下:

    以上测试代码和图片引用自:

     http://cenalulu.github.io/python/gil-in-python/

    过程证明了因为GIL的存在,导致python在使用多线程的时候反而不如顺序执行快。

      此处我又温习了一下python线程:

      线程的顺序执行还是多线程并发,取决于join函数的位置。join函数的作用是等待当前线程结束,所以每一个线程创建之后,调用start函数,这是在后面跟上该线程的join函数,那么就是顺序执行,如果多个线程先完成创建和start,最后加上join函数,那么就变成了多线程并发。

  • 相关阅读:
    6_java_maven
    线性代数 linear algebra
    hadoop_wordcount_1027
    hadoop_worddistinct_1030
    hadoop_wordcount_1023
    搭建伪分布式_笔记
    linux-sunrpc
    linux-volatile
    linux---asmlinkage
    dqs_linux-1
  • 原文地址:https://www.cnblogs.com/shengguorui/p/10802056.html
Copyright © 2011-2022 走看看