昆山网站建设费用,城市建设理论研究收录网站,怎么简单制作一个网页,网站制作工作室24小时接单写过爬虫的都知道#xff0c;爬虫的性能瓶颈在于IO#xff0c;因为爬虫是一个IO密集型业务#xff0c;程序需要发起网络请求#xff0c;必然就有IO阻塞#xff0c;
通常请求一个URL耗时要几百毫秒到几秒不等#xff0c;而我们的CPU处理速度惊人#xff0c;两者的速度就好…写过爬虫的都知道爬虫的性能瓶颈在于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等一些窗口可以打饭菜或者米粉麻辣烫什么的。
但是每一个窗口又有打这些菜的师傅。
那么这些窗口就是进程。
那个那些窗口里面打菜的师傅就是线程。
这个食堂就是系统了系统去分配这些进程。