同步与异步以及线程与进程

写过爬虫的都知道,爬虫的性能瓶颈在于IO,因为爬虫是一个IO密集型业务,程序需要发起网络请求,必然就有IO阻塞,
通常请求一个URL耗时要几百毫秒到几秒不等,而我们的CPU处理速度惊人,两者的速度就好比乌龟跟火箭的差别。
在单线程同步阻塞程序中,如果要获取一个网站所有的URL,假设100个URL,平均每个URL请求的时间是1秒,
那么在单线程同步场景下,最快也需要100秒钟,才能把所有的页面爬取下来。
于是,我们想到了更好的一种办法就是采用多线程或者多进程,但是由于在Python中臭名昭著的GIL,导致做不到真正的并行运算,
在同一时间内,就算有多核CPU,也无法被利用起来,这样虽然能做到并发,但是没法并行,在单个CPU里切换线程,还有切换成本,以及线程的创造成本。
如果使用多进程,虽然能利用多核处理的优势,但是多进程的创建成本比线程更高,而IO密集型任务,CPU不是瓶颈。
所以,后来Python引入了异步编程,异步编程使得CPU不再需要再去等待耗时的操作,而是让出CPU时间给其他任务执行,

这样假如有100个任务,每个任务是1秒钟,就可以做到理论上只需要1秒钟就可以完成所有的任务。


同步与异步

异步操作的本质

所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础。 
熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。
DMA就是直接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。
只要CPU在发起数据传输时发送一个指令,硬件就开始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。
这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。

同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)

所谓同步,就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由*调用者*主动等待这个*调用*的结果。
而异步则是相反,*调用*在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。
而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。典型的异步编程模型比如Node.js
举个通俗的例子:
你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

阻塞与非阻塞

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
还是上面的例子,
你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,
如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。
在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。

进程和线程的区别

1.定义
进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程:进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),
但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

2.关系
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。

3.区别
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响。
而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,
所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。
但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
2) 线程的划分尺度小于进程,使得多线程程序的并发性高。
3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
4) 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。
   但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。
   但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

4.优缺点
线程和进程在使用上各有优缺点:
线程执行开销小,但不利于资源的管理和保护;而进程正相反。

举例

开个QQ,开了一个进程;开了迅雷,开了一个进程。在QQ的这个进程里,传输文字开一个线程、传输语音开了一个线程、弹出对话框又开了一个线程。
Why: 
由于CPU与其他PC资源之间速度的不协调,人们想提高资源利用率,所以人们提出了多任务系统。
得益于CPU的计算速度,我们可以“同时”运行多个任务,实质上是多个任务之间轮流使用CPU资源,由于速度超快,给用户的感觉就是连续的。
How: 
1)任务的执行需要依赖各个PC资源,我们可以称为计算机执行的上下文环境。
   要实现“同时执行”,就需要不断轮换,为了后来继续从当前状态执行下去,计算机需要保存切换前的程序上下文。
   所以有了进程:用进程去描述程序当前上下文的状态信息----内存位置、变量值、任务ID……所以,进程是资源分配的单位。
   一般来说宏观上可以看做是一个软件的运行,例如一个word文档的打开。
2)多个任务之间切换因为要保存上下文、调入上下文,一旦多了的时候,还是有一定的时间消耗的。
   为了进一步提高资源利用率,人们在进程中,引入了线程,线程只是CPU轮流调度的单位,其他上下文信息用所在进程中的。
   这样上下文切换的耗时就降了下来。同样的,宏观上来可以看做是一个软件中的多个处理功能,例如上述打开word中拼写检查功能、字体加粗……
So, What: 
一般来说,进程是资源的分配单位,线程是CPU在进程内切换的单位,线程属于进程。所以运行某个软件,相当于开了一个进程。
在这个软件运行的过程里(在这个进程里),多个工作支撑的完成QQ的运行,那么这“多个工作”分别有一个线程。

再打一个通俗易懂的比方吧!
比如你去一个食堂吃饭。里面有A,B,C,D等一些窗口可以打饭菜或者米粉麻辣烫什么的。
但是每一个窗口又有打这些菜的师傅。
那么这些窗口就是进程。
那个那些窗口里面打菜的师傅就是线程。
这个食堂就是系统了,系统去分配这些进程。

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

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

相关文章

Django 新建account应用

一、应用基本配置 1、在根目录下新建account应用。python manage.py startapp account 2、在项目根目录的项目目录的setting下的INSTALLED_APPS中添加 ‘account’ 3、在项目根目录的项目目录的url.py中进行URL配置。添加 url(r^account/,include(account.urls,namespaceac…

【Python爬虫】Windows环境下wxpy不需每次登陆重新扫描

有时候我们想每天向你女朋友或者某人发送一条信息(通过线程控制或者每天自动任务);此外我们可以通过更改wxpy中Bot()中参数,保存缓存不用每次都扫描二维码。 以下代码来源于:http://www.cnblogs.com/botoo/p/8622379.html from …

pycharm中windows找不到chrome解决办法

这种问题主要是因为在pycharm中关于chrome的安装路径配置不正确造成的,具体的解决办法为: 打开pycharm–》File–》setting–》Tools–》Web Browsers 然后添加chrome安装路径,然后就成功啦~ 转载自:https://blog.csdn.net/csz…

Win10系统设置任务计划执行python脚本

上一篇文章说了通过Python中的wxpy在微信每天发送一条消息到女朋友或者某个人,通过线程方式每天发送次消息。 这里主要说如何通过window10自带的“任务计划程序”,每天在指定时间发送一条消息。 1. 首先通过windows 10系统左下角输入框输入“任务计划程…

bootstrap里col-xs , col-sm ,col-md,col-lg的区别

前言 对于一些初学boostrap的同学来说,肯定也像我一样傻傻的搞不懂col--*都是要怎么使用吧,我刚开始也表示一脸懵逼,后来查阅了这篇文章才搞懂了他们之间的区别,我整理了一下供大家一起学习。 摘要: bootstrap栅栏系统css中的col…

【Word 】隐藏功能生成特殊线

有时候在用word进行文字处理时,有一些方法可以快速生成特殊的线,以下是具体的一些方法: 1.输入3个“”,再按回车键Enter,生成一条双直线 2.输入3个“~~~”,再按回车键Enter,生成一条波浪线 3.输…

Django - - - -视图层之视图函数(views)

阅读目录(Content) 视图层之视图函数(views) 一个简单的视图1.HttpRequest2.HttpResponse 1.render 函数 2.redirect 函数对比render与redirect: 回到顶部(go to top) 视图层之视图函数(views) 一个视图函数,简称视图,是一个简单的Python …

【Excel】设计简单抽奖小程序

其实我们可以通过excel做一个抽奖的小程序。比如搞活动送奖品,我们就可以通过这个小程序抽中奖名单 中奖名单下面输入“INDIRECT("A"&RANDBETWEEN(4,12))”,然后按F9进行抽奖 其中用到了两个函数INDIRECT(单元格引用,[引用样式…

python manage.py syncdb Unknown command: 'syncdb'问题解决方法

在django1.9后的版本中,python manage.py syncdb命令修改为python manage.py migrate,执行正常。 转载自https://blog.csdn.net/u010309756/article/details/53486924

【Python】retrying模块使用场景

大家在做数据抓取或者用selenium自动化进行元素定位的时候,经常遇到由于网络问题导致的抓取数据失败,或者定位元素失败。 针对这种情况,我们可以通过设置等待时间去控制,其实还有一种方法,就是使用retrying&#xff0c…

Django连接现有mysql数据库

1、打开cmd后cd到项目位置 2、建立项目 django-admin startproject test2 3、编辑项目中的配置文件, mysite/settings.py ,告诉Django你的数据库连接参数和数据库名。具体的说,要提供 DATABASE_NAME , DATABASE_ENGINE , DATABASE_USER , DATABASE_PASSWORD , DATA…

【Python】Pygame模块设计游戏

Pygame是一个跨平台Python模块,专为电子游戏设计,包含图像、声音。建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚。 Pygame的历史 Pygame是一个利用SDL库的写就的游戏库&#xff…

Django 入门

1.用cmd cd到文件的目录下 2、运行python manage.py runserver 0.0.0.0:8000 即可启动服务器 3、在网页中输入127.0.0.1/hello 或者127.0.0.1即可 Helloworld项目: 超级用户名:admin 密码:******** 创建Django项目: 1、用cmd命令行…

【Python爬虫】下载微信公众号图片

大家用爬虫下载图片时肯定遇到过https://demo?wx_fmtjpeg链接的图片,常见的就是微信公众号的图片。 遇到链接图片用普通的方式是无法爬取下来的,我们可以用urllib.request进行简单爬取,具体源码如下: # 2018年10月07日 13点30分…

关于Django中的数据库操作API之distinct去重的一个误传

django提供的数据库操作API中的distinct()函数,了解SQL语句的读者都应该知道,DISTINCT关键字可以在select操作时去重。django里的这个distinct()函数也是这个功能,通常的用法是我们要取出一张表中的某一列的所有值,并且只取出不重…

【工具】Jupyter Notebook介绍

在数据分析的道路上,你一定曾有过为新发现而激动不已的时刻,此时你急于将自己的发现告诉大家,却遇到了这样的问题:如何将我的分析过程清晰地表述出来呢? 为了能与同行们有效沟通,你需要重现整个分析过程&am…

Django模板之显示QuerySet内容,字典中内容

camera和idproject都为QuerySet,如下图为验证 camera内容显示方法为: 可以看出idproject中迭代为dict类型。HTML中读写形式为: 显示结果: 参考自 https://blog.csdn.net/gaoxiaoba/article/details/52469614

Python操作文件和目录

读写文件比较简单,有一点特别注意就好了 windows下Python默认打开的文件以gbk解码,而一般我们的文件是utf-8编码的,所以如果文本含有中文,就会出现异常或者乱码。此时手动添加encodingutf-8表示以utf-8的方式打开。 当然Python写…

Docker高效管理指南:一键清理、停止与删除所有容器和镜像

前言 在当今Java开发的日常工作中,Docker已经成为一项不可或缺的技术。它不仅提供了便捷的开发和部署方式,还为项目的可移植性和可伸缩性带来了新的可能性。我们熟悉了一些基本的Docker命令,如启动、关闭、删除容器以及删除镜像,…

【Python】提升Python程序性能的好习惯

掌握一些技巧,可尽量提高Python程序性能,也可以避免不必要的资源浪费。 追求性能极限是一个有趣的游戏, 而过度优化就会变成嘲弄了。虽然Python授予你与C接口无缝集成的能力, 你必须问自己你花数小时的艰辛优化工作用户是否买帐. 另一方面, 牺牲代码的可…