既然有了GIL锁,CPython还要多线程干什么?

'''
GIL:全局解释器锁的来历
四核:同一时刻真正有四个任务在运行,多核的意义在于此
单核:看上去是并发的,因为进行了上下文切换,单核永远是串行的,并发是假象
CPython中不论有多少核,只有一个核心的CPU资源被使用,因为同一时间只有一个线程能拿到GIL锁。
为什么这样设计呢?CPython的线程是调用操作系统的c语言的原生线程,该线程不是线程安全的。balabalabala...
===================官方解释======================
在CPython中,全局解释器锁或GIL是一个互斥锁,
这个锁是必要的,主要是因为CPython的内存管理不是线程安全的。
(然而,由于GIL的存在,其他特征已经发展成依赖于这个锁形成的线程安全环境)
=================================================
由于GIL是全局的,所以在多线程(多核)时,线程需满足两个条件才能执行
1、被操作系统调度出来【操作系统允许它占用CPU】 2、获取到GIL锁【CPython解释器允许它执行指令】
怎样避免GIL影响性能?就是减少GIL锁对线程的影响
1、在单核机器上Python和其他语言一样,“多线程”只是是假象实际上还是单线程。第2条总能满足,性能没有影响
2、在多核机器上Python只有一个核心在使用。因为多核多线程中,同时只有一个线程申请到GIL。所以要尽量减少
对GIL的申请,例如:全IO密集型任务时才使用多线程,
避免在计算密集型任务中使用Python的多线程(因为计算需要CPU资源,会频繁申请GIL锁,造成其他线程等待)
================================================
用户程序锁:
还有一个锁,用户程序锁,跟GIL没有关系。这个锁是保证某个全局变量的修改必须是串行的
假设有全局变量num=0,线程作用是对num执行加1的操作。
在线程调度的时候,A线程获取到num=0,A执行到一半,CPU执行B线程,
B线程将num修改num=1,CPU继续执行A线程,A线程执行完毕,将num修改成1,而num在AB线程执行完其实应该为2
此时就应该对num变量加锁。这个锁就是用户程序锁,这个锁不同于GIL锁。GIL锁是同一时间只能有一个线程使用
CPU资源,要保证同一时间只有一个线程访问某块数据就需要“用户程序锁”
=====================================================
在Python2.x版本+某些操作系统里不加用户程序锁会导致结果不准。
在Python3.x版本+某些操作系统里不确定是否有同样的问题,但是最好加上。
'''
import threading
import time lock = threading.Lock()
class Foo:
num = 0
@classmethod
def run(cls):
time.sleep(2)
lock.acquire()
cls.num += 1
lock.release()
thread_objs = []
for i in range(20):
thread_objs.append(threading.Thread(target=Foo.run, args=()))
start_time = time.time()
for i in thread_objs:
i.start()
for i in thread_objs:
i.join()
print(Foo.num) #
print(time.time()-start_time) # 2.0051145553588867

GIL:全局解释器锁 VS 用户程序锁的更多相关文章

  1. 【转】进程、线程、 GIL全局解释器锁知识点整理

    转自:https://www.cnblogs.com/alex3714/articles/5230609.html 本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线 ...

  2. Python之路-python(paramiko,进程和线程的区别,GIL全局解释器锁,线程)

    一.paramiko 二.进程.与线程区别 三.python GIL全局解释器锁 四.线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生 ...

  3. Python自动化 【第九篇】:Python基础-线程、进程及python GIL全局解释器锁

    本节内容: 进程与线程区别 线程 a)  语法 b)  join c)  线程锁之Lock\Rlock\信号量 d)  将线程变为守护进程 e)  Event事件 f)   queue队列 g)  生 ...

  4. GIL全局解释器锁

    1. 什么是GIL全局解释器锁 GIL本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL,同一进程内的多个线程     必须抢到GIL之后才能使用Cpython解释器来执行自己的代码,即 ...

  5. 网络编程-Python高级语法-GIL全局解释器锁

    知识点:GIL全局解释器锁其实和Python没有任何关系,是由于当初编写Python解释器时留下的,它只对多线程有影响,GIL保证同一时刻只有一个线程在运行,即使是多核配置电脑,同一时刻也只会让一个线 ...

  6. 进程、线程与GIL全局解释器锁详解

    进程与线程的关系: . 线程是最小的调度单位 . 进程是最小的管理单元 . 一个进程必须至少一个线程 . 没有线程,进程也就不复存在 线程特点: 线程的并发是利用cpu上下文的切换(是并发,不是并行) ...

  7. 关于python的GIL全局解释器锁的简单理解

    GIL是解释器内部的一把锁,确切一点说是CPython解释器内部的一把锁,所以要注意区分 这和我们在Python代码中使用线程锁Lock并不是一个层面的概念. 1. GIL产生的背景: 在CPytho ...

  8. [py]GIL(全局解释器锁):多线程模式

    在多线程 时同一时刻只允许一个线程来访问CPU,直到解释器遇到I/O操作或者操作次数达到一定数目时才会释放GIL 参考 Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务.多个P ...

  9. 10 并发编程-(线程)-GIL全局解释器锁&死锁与递归锁

    一.GIL全局解释器锁 1.引子 在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势 首先需要明确的一点是GIL并不是Python的特性,它是在实现Pyt ...

随机推荐

  1. Xamarin.Android多窗口传值【1】

    这种非常常见的场景我觉得大家都遇到过,那么我么可以通过Activity进行编码传值. using System.Text; using System; using Android.App; using ...

  2. Netty 简介

    上文我们介绍了NIO和BIO的区别,NIO相对于BIO是一次很大的进步.但我们平时开发中并不会使用NIO.这是因为NIO在开发中存在以下问题 NIO的类库和API繁杂,使用麻烦,需要熟练掌握Selec ...

  3. JVM(1)---虚拟机在运行期的优化策略

    1.解释器与JIT编译器 首先我们先来了解一下运行在虚拟机之上的解释器与JIT编译器.当我们的虚拟机在运行一个java程序的时候,它可以采用两种方式来运行这个java程序: 采用解释器的形式,也就是说 ...

  4. TypeScript 基础知识点整理

    一.TypeScript的特点 1.支持ES6规范 2.强大的IDE支持(集成开发环境) 允许为变量指定类型,减少你在开发阶段犯错误的几率. 语法提示,在IDE编写代码时,它会根据你所处的上下文把你能 ...

  5. 按行切割大文件(linux split 命令简版)

    按行切割大文件(linux split 命令简版) #-*- coding:utf-8 -*- __author__ = 'KnowLifeDeath' ''' Linux上Split命令可以方便对大 ...

  6. 我对C#的认知。

    关于开发者的技术水平到底该如何定义,到底一个人的技术水平应该定位在高.中.低的标准是什么呢?很多人觉得这是一个仁者见仁的问题,有人觉得根据公司的那个员工等级判断.答案是肯定不是,从纯开发技术的角度来分 ...

  7. Linux rsync 两个目录镜像备份

    rsync安装篇 rsync是一款配置简单,功能全面的安全备份软件,具体的功能介绍可以参考手册.这里和大家分享一下rsync在CentOS下的部署. 1.安装rsync,并通过xinetd管理rsyn ...

  8. [HEOI2018] 秘密袭击coat

    Description 给定一棵 \(n\) 个点的树,每个点有点权 \(d_i\) ,请对于树上所有大于等于 \(k\) 个点的联通块,求出联通块中第 \(k\) 大的点权之和.\(n\le 166 ...

  9. Java学习笔记——判断字符Character类

    常用方法 下面所说的均是静态方法,也就是可以不创建对象直接调用 例:Character.isLetter(char c); isLetter 判断参数是否为字母(不分大小写),返回结果 isDigit ...

  10. webpack入门教程--2

    这次是创建第二个JS文件. 我们还是在app文件夹中创建一个叫做book2.js的JS文件,并在其中输入以下代码: module.exports = "It works from book2 ...