python 并发编程 多线程 GIL全局解释器锁基本概念

首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。

就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。

>有名的编译器例如GCC,INTEL C++,Visual C++等。Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。

像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把GIL归结为Python语言的缺陷。所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL

只有CPython 有GIL全局解释器锁

二 GIL介绍

GIL本质就是一把互斥锁,既然是互斥锁,所有互斥锁的本质都一样,都是将并发运行变成串行,以此来控制同一时间内共享数据只能被一个任务所修改,进而保证数据安全。

可以肯定的一点是:保护不同的数据的安全,就应该加不同的锁。

执行python程序默认会生成一个进程 这个进程就是这个python解释器程序

#! /usr/bin/env python
# -*- coding: utf-8 -*- import time
import os print os.getpid()
time.sleep(1000)
[root@salt-server-192 ~]# python create_process.py
1343
#在windows下查看
tasklist |findstr python #在linux下下查看
ps -aux |grep python

在一个python的进程内,不仅有这个程序的的主线程或者由该主线程开启的其他线程,还有解释器开启的垃圾回收等解释器级别的线程,总之,所有线程都运行在这一个进程内

1、所有数据都是共享的,这其中,代码作为一种数据也是被所有线程共享的(test.py的所有代码以及Cpython解释器的所有代码)
例如:test.py定义一个函数work,在进程内所有线程都能访问到work的代码,于是我们可以开启三个线程然后target都指向该代码,能访问到意味着就是可以执行。

2、所有线程的任务,都需要将任务的代码当做参数传给解释器的代码去执行,即所有的线程要想运行自己的任务,首先需要解决的是能够访问到解释器的代码。

接上:

如果多个线程的target=work,那么执行流程是

多个线程先访问到解释器的代码,即拿到执行权限,然后将target的代码交给解释器的代码去执行

参考python执行程序 三部曲文章 >>

python 并发编程 多线程 GIL全局解释器锁基本概念

1.每起一个进程,在内存空间都会默认生成一个主线程

线程的代码 taget参数 指向python代码 。然后把python代码,当做参数传给解释器的代码去执行,即所有的线程要想运行自己的任务,首先需要解决的是能够访问到解释器的代码。

图片上的参数就是python代码

2.进程内可以开好多个线程

CPython里面有一个垃圾回收机制 也是执行解释器代码,所以在进程内,内存空间会有一个垃圾回收线程

垃圾回收线程运行的是python解释器代码

python 并发编程 多线程 GIL全局解释器锁基本概念

因为进程内有4个线程,垃圾回收线程和其他线程会同时执行,垃圾回收线程有可能和其他线程工作冲突,导致数据不安全,

所以要控制 这些线程一个个运行 需要在CPython解释器里加锁

python 并发编程 多线程 GIL全局解释器锁基本概念

解释器的代码是所有线程共享的,所以垃圾回收线程也可能访问到解释器的代码而去执行,这就导致了一个问题:对于同一个数据100,可能线程1执行x=100的同时,而垃圾回收执行的是回收100的操作,解决这种问题没有什么高明的方法,就是加锁处理,如下图的GIL,保证python解释器同一时间只能执行一个任务的代码

python 并发编程 多线程 GIL全局解释器锁基本概念

加了互斥锁每个线程要运行,每个线程抢着加锁, 一次执行 只能加锁require() 一次  再加锁require() 一次就变成阻塞状态 要等到释放release() 之后 再加锁require(),

同一时间只能有一个线程抢到锁,其他线程都要等待

1.GIL全局解释器锁本质就是互斥锁,加了GIL全局解释器锁 同时运行的多个线程,变成一个一个运行 ,效率低了, 但保证数据安全

2.只有Cpython解释器才有GIL ,有了互斥锁,对CPython 解释器来说 每启动一个进程 这个进程内的多个线程 同一时间只能有一个在运行

3.也就是说python多线程不能用多核优势,在CPython 想用多核只能用多进程 单核只适合多线程

4.垃圾回收机制是否一直存在?

CPython的垃圾回收机制 定时销毁 定时启动的

上一篇:暑期训练狂刷系列——Hdu 3506 Largest Rectangle in a Histogram (单调栈)


下一篇:hiho_1058_combination_lock