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

 

 

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

就比如C++是一套语言(语法)标准,可是能够用不一样的编译器来编译成可执行代码。python

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

像其中的JPython就没有GIL。然而由于CPython是大部分环境下默认的Python执行环境。因此在不少人的概念里CPython就是Python,也就想固然的把GIL归结为Python语言的缺陷。因此这里要先明确一点:GIL并非Python的特性,Python彻底能够不依赖于GILwindows

只有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的进程内,不只有这个程序的的主线程或者由该主线程开启的其余线程,还有解释器开启的垃圾回收等解释器级别的线程,总之,全部线程都运行在这一个进程内ui

 

 

一、全部数据都是共享的,这其中,代码做为一种数据也是被全部线程共享的(test.py的全部代码以及Cpython解释器的全部代码)
例如:test.py定义一个函数work,在进程内全部线程都能访问到work的代码,因而咱们能够开启三个线程而后target都指向该代码,能访问到意味着就是能够执行。spa

二、全部线程的任务,都须要将任务的代码当作参数传给解释器的代码去执行,即全部的线程要想运行本身的任务,首先须要解决的是可以访问到解释器的代码。

 

接上:

若是多个线程的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的垃圾回收机制 定时销毁 定时启动的

相关文章
相关标签/搜索