python多线程单核_002_Python多线程相当于单核多线程的论证

很多人都说python多线程是假的多线程!下面进行论证解释:

一、

我们先明确一个概念,全局解释器锁(GIL)

Python代码的执行由Python虚拟机(解释器)来控制。Python在设计之初就考虑要在主循环中,同时只有一个线程在执行,就像单CPU的系统中运行多个进程那样,内存中可以存放多个程序,但任意时刻,只有一个程序在CPU中运行。同样地,虽然Python解释器可以运行多个线程,只有一个线程在解释器中运行。

对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同时只有一个线程在运行。在多线程环境中,Python虚拟机按照以下方式执行。

1.设置GIL。

2.切换到一个线程去执行。

3.运行。

4.把线程设置为睡眠状态。

5.解锁GIL。

6.再次重复以上步骤。

对所有面向I/O的(会调用内建的操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。如果某线程并未使用很多I/O操作,它会在自己的时间片内一直占用处理器和GIL。也就是说,I/O密集型的Python程序比计算密集型的Python程序更能充分利用多线程的好处。

我们都知道,比方我有一个4核的CPU,那么这样一来,在单位时间内每个核只能跑一个线程,然后时间片轮转切换。但是Python不一样,它不管你有几个核,单位时间多个核只能跑一个线程,然后时间片轮转。看起来很不可思议?但是这就是GIL搞的鬼。任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个不带GIL的解释器。

我们不妨做个试验:

#coding=utf-8

from threading import Thread

def loop():

while True:

pass

if __name__ == '__main__':

for i in range(3):

t = Thread(target=loop)

t.start()

while True:

pass

Windows状态如下:

Mac状态如下:

我们发现CPU利用率并没有占满,大致相当于单核水平。

而如果我们变成进程呢?

我们改一下代码:

#coding=utf-8

from multiprocessing import Process

def loop():

while True:

pass

if __name__ == '__main__':

for i in range(3):

t = Process(target=loop)

t.start()

while True:

pass

Windows状态如下:

Mac状态如下:

结果直接飙到了100%,说明进程是可以利用多核的!

为了验证这是Python中的GIL搞得鬼,我试着用Java写相同的代码,开启线程,我们观察一下:

package com.darrenchan.thread;

public class TestThread {

public static void main(String[] args) {

for (int i = 0; i < 3; i++) {

new Thread(new Runnable() {

@Override

public void run() {

while (true) {

}

}

}).start();

}

while(true){

}

}

}

效果如下:

由此可见,Java中的多线程是可以利用多核的,这是真正的多线程!而Python中的多线程只能利用单核,这是假的多线程!

难道就如此?我们没有办法在Python中利用多核?当然可以!刚才的多进程算是一种解决方案,还有一种就是调用C语言的链接库。对所有面向I/O的(会调用内建的操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。我们可以把一些 计算密集型任务用C语言编写,然后把.so链接库内容加载到Python中,因为执行C代码,GIL锁会释放,这样一来,就可以做到每个核都跑一个线程的目的!

可能有的小伙伴不太理解什么是计算密集型任务,什么是I/O密集型任务?

计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。

计算密集型任务由于主要消耗CPU资源,因此,代码运行效率至关重要。Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。

第二种任务的类型是IO密集型,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。

IO密集型任务执行期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,用运行速度极快的C语言替换用Python这样运行速度极低的脚本语言,完全无法提升运行效率。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。

综上,Python多线程相当于单核多线程,多线程有两个好处:CPU并行,IO并行,单核多线程相当于自断一臂。所以,在Python中,可以使用多线程,但不要指望能有效利用多核。如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点。不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457524.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

detail:JSON parse error - Expecting value: line 1 column 1 (char 0)

detail":"JSON parse error - Expecting value: line 1 column 1 (char 0) 在调用接口时返回400错误&#xff0c;详情是 {detail":"JSON parse error - Expecting value: line 1 column 1 (char 0)"}原因是传送数据的格式有问题&#xff0c;不要使用…

【IDEA 2016】intellij idea tomcat jsp 热部署

刚开始用IDEA&#xff0c;落伍的我&#xff0c;只是觉得IDEA好看。可以换界面。想法如此的low。 真是不太会用啊&#xff0c;弄好了tomcat。程序启动竟然改动一下就要重启&#xff0c;JSP页面也一样。 IDEA可以配置热部署&#xff0c;打开tomcat配置页面&#xff0c;将红框处&a…

C# where用法解析

where 子句用于指定类型约束&#xff0c;这些约束可以作为泛型声明中定义的类型参数的变量。1.接口约束。例如&#xff0c;可以声明一个泛型类 MyGenericClass&#xff0c;这样&#xff0c;类型参数 T 就可以实现 IComparable<T> 接口&#xff1a;public class MyGeneric…

ubuntu进入桌面自动启动脚本_在 Ubuntu 下开机自启动自己的 QT 程序而不启动 Ubuntu 的桌面...

1. /etc/profile 方式实现这个功能&#xff0c;要完成两步&#xff1a;1、系统设置-> 用户账户-> 点击我的账户-> 点击右上角的解锁-> 打开自动登录-> 点击右上角的锁定-> 退出系统设置2、在 /etc/profile 文件的开头添加执行 qt 程序的命令。如&#xff1a;…

Java obj与JSON互转(jackson)

JSON 解析 常见的json解析器&#xff1a; jsonlibGson(谷歌)fastjson(阿里)jackson(Spring内置) jackson 依赖jar包 jackson-annotations/jackson-core/jackson-databind/ 官网下载地址 1. Java对象转JSON 1.1 核心对象 ObjectMapper 1.2常用转换方法 writeValue(参…

如何制作一个简单的APP应用软件?

如今随着移动智能手机的普及&#xff0c;让APP的市场一片繁荣&#xff0c;现在市场上的APP数量数不胜数&#xff0c;对于APP开发的我们很多外行人也许认为&#xff0c;开发APP是不是特别难&#xff0c;是不是只有资历很高的程序员才能够完成这个任务&#xff0c;或者说要想开发…

I/O重定向

每个进程都至少有3个信息&#xff1a;“标准输入”stdin、“标准输出”stdout、和“标准出错”stderr。标准输入通常来自键盘&#xff0c;标准输出和标准错误输出通常被发往屏幕&#xff08;并不会保存在磁盘文件中&#xff09;。有些时候&#xff0c;需要从文件读取输入&#…

java 自动装拆箱

title: “java 自动装拆箱” tags: Java 将基本数据类型封装成对象的过程叫做装箱&#xff08;boxing&#xff09;&#xff0c;反之基本数据类型对应的包装类转换为基本数据类型的过程叫做拆箱&#xff08;unboxing&#xff09;; 基本数据类型与其他对象的区别 基本数据类型 …

设计模式11---组合模式(Composite Pattern)

一、组合模式定义 将对象组合成树形结构以表示“部分-整体”的层次结构&#xff0c;使得用户对单个对象和组合对象的使用具有一致性。Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compos…

Linux 多核下绑定硬件中断到不同 CPU(IRQ Affinity)

转载 - Linux 多核下绑定硬件中断到不同 CPU&#xff08;IRQ Affinity&#xff09; 作者 digoal 日期 2016-11-20 标签 Linux , IRQ , 中断 , CPU亲和 , 绑定中断处理CPU 背景 原文 http://www.vpsee.com/2010/07/load-balancing-with-irq-smp-affinity/ 原文 硬件中断发生频繁…

请列举你了解的分布式锁_这几种常见的“分布式锁”写法,搞懂再也不怕面试官,安排!...

什么是分布式锁&#xff1f;大家好&#xff0c;我是jack xu&#xff0c;今天跟大家聊一聊分布式锁。首先说下什么是分布式锁&#xff0c;当我们在进行下订单减库存&#xff0c;抢票&#xff0c;选课&#xff0c;抢红包这些业务场景时&#xff0c;如果在此处没有锁的控制&#x…

leetcode 268

等差数列求值 1 class Solution {2 public:3 int missingNumber(vector<int>& nums) {4 int nnums.size();5 int kn*(n1)/2;6 for(int i0;i<n;i)7 k-nums[i];8 return k;9 } 10 }; 转载于:https://www.cnblogs.…

301缓存重定向?301 Moved Permanently (from disk cache)

今天在写一个博客系统时&#xff0c;发现首页数据经常刷新不出来&#xff0c;甚至后端根本就没有接受到这个请求&#xff0c;以为是Ajax的问题&#xff0c;但通过抓包发现Ajax请求确实已经发出去了&#xff0c;但状态码是 301 Moved Permanently (from disk cache),301是永久重…

Firefox 50优化Electrolysis

Mozilla正式发布Firefox 50。最新的版本中提升了来自多个内容进程用户的用户体验&#xff0c;并修复了十几个高影响的安全漏洞。\\在Firefox最新版本的变更中&#xff0c;我们注意到了它对于Electrolysis的进一步改进。Electrolysis是Mozilla实现在后台进程中呈现和执行web相关…

ModuleNotFoundError: No module named '_ctypes' ERROR:Command errored out with exit status 1: python

Ubuntu下载 nginx 时报错&#xff1a; ERROR: Command errored out with exit status 1:command: /usr/local/bin/python3.7 -c import sys, setuptools, tokenize; sys.argv[0] ""/tmp/pip-install-7e0xdb36/uwsgi/setup.py""; __file__""/tmp…

python opc plc_PYthon简易OPC数据采集写入Access

利用hollias comm opcserver 与Python实现交互。代码如下&#xff1a;# -*- coding: utf-8 -*-from sys import *from getopt import *#from os import * 造成f open(test.txt, r) TypeError: an integer is required错误import signalimport sysimport osimport typesimport …

边工作边刷题:70天一遍leetcode: day 73

Read N Characters Given Read4 I/II 要点&#xff1a;这题的要点就是搞清楚几个变量的内在逻辑&#xff1a;只有buffer是整4 bytes的。而client要读的bytes&#xff08;需求&#xff09;和实际上disk上有的bytes&#xff08;供给&#xff09;都是不整的。所以&#xff0c; 循环…

javascript时间戳和日期字符串相互转换

1 <html xmlns"http://www.w3.org/1999/xhtml">2 <head>3 <meta http-equiv"Content-Type" content"text/html; charsetutf-8" />4 <script type"text/javascript">5 // 获取当前时间戳(以s为单位)6 var time…

wireshark 十六进制过滤_CTF流量分析之wireshark使用

01.基本介绍在CTF比赛中&#xff0c;对于流量包的分析取证是一种十分重要的题型。通常这类题目都是会提供一个包含流量数据的pcap文件&#xff0c;参赛选手通过该文件筛选和过滤其中无关的流量信息&#xff0c;根据关键流量信息找出flag或者相关线索。pcap流量包的分析通常都是…

vim 插件管理

1  进入自己的vim mkdir ./bundle/vundle 2  在vimrc同级中执行 git clone https://github.com/gmarik/vundle.git ./bundle/vundle 将一些插件文件 下载到./bundle/vundle中 3  编写自己的vim配置&#xff0c;其实很简单 set nocompatible " be iMp…