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执行程序 三部曲文章 >>

 

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

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

图片上的参数就是python代码

 

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

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

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

 

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

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

 

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

 

 

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

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

 

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

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

 

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

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

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

posted @ 2019-06-21 12:00  minger_lcm  阅读(323)  评论(0编辑  收藏  举报