协程

python面试题整理(二)

旧时模样 提交于 2019-12-01 22:42:42
1、进程,线程,协程定义,有什么区别    进程是操作系统分配资源的最小单位,一个进程对应一块CPU   线程是进程中的某一个控制单元,是CPU调度的最小单元,线程之间相互独立,进程结束线程也会结束,一个进程至少要有一个线程   协程是更加轻量级的存在,不是由CPU进程管理而是由程序员管理,在执行一个函数过程中可以中断执行另一个函数,执行一个函数过程就叫协程,python3以前使用 yield 表示协程,yield关键字一般用于做生成器,实现在函数中暂停的效果,python3.3以后出现 yield from 后面跟可迭代对象,3.5以后使用 async和await 实现原生协程。     区别:     (1) 线程之间切换是由操作系统决定的 ,切换速度特别快,但是切换频率太高, 协程之间切换由程序决定 ,不会像线程切换那么耗费资源,在高并发下执行效率更高,   性能更优     (2)协程中控制共享资源不加锁     (3)协程使用同步的方式实现异步,在单进程里实现任务切换 2、子进程是什么    在一个进程中创建开启另一个进程,这个进程称为子进程,即在父进程中创建的进行 3、僵尸进程知道吗    父进程还在执行,子进程执行完毕后不会立即退出,操作系统会清理内存空间,但是保留进程号(pid),等待父进程清理资源,这个时候子进程成为僵尸进程 4、线程和协程有什么区别     

协程

独自空忆成欢 提交于 2019-12-01 22:28:39
为什么要有协程? 因为想要在单线程内实现并发的效果。 因为CPthon有GIL锁,限制了在同一个时间点,只能执行一个线程 所以想要在执行一个线程的期间,充分的利用CPU的性能 所以才有了想在单线程内实现并发的效果。 并发:切换+保存状态 cpu是为什么要切换? 1 因为某个程序阻塞了 2 因为某个程序用完了时间片 很明显 解决1 这个问题才能提高效率 所以想要实现单线程的并发,就要解决在单线程内,多个任务函数中,某个任务函数遇见IO操作,马上自动切换到其他任务函数去执行。 协程:是一个比线程更加轻量级的单位,是组成线程的各个函数 协程本身没有实体 greenlet模块:能简单的实现函数与函数之间的切换,但是遇到IO操作,不能自动切换到其他函数中 (1) 注册一下函数func,将函数注册成一个对象f1 f1 = greenlet(func) (2) 调用func,使用f1.switch(),如果func需要传参,就在switch这里传即可 gevent模块:可以实现在某函数内部遇到IO操作,就自动的切换到其他函数内部去执行 g = gevent.spawn(func,参数) 注册一下函数func,返回一个对象g gevent.join(g) #等待g指向的函数func执行完毕,如果在执行过程中,遇到IO,就切换 gevent.joinall([g1,g2,g3])#等待g1 g2

单线程多任务异步协程

孤街浪徒 提交于 2019-12-01 22:18:49
目录   1. 概念讲解   2. 多任务异步协程理解   3.基于aiohttp模块异步网络请求实现数据爬取及数据解析 一、需要了解的概念    特殊函数 :如果async修饰了一个函数的定义,那么该函数就变成了一个特殊函数,      特殊之处 :特殊函数被调用后函数内部实现语句不会被立即执行      该函数调用之后会返回一个协程对象       协程对象 :特殊函数调用后可以返回一个协程对象     协程 == 特殊函数    任务对象 :对协程对象的进一步封装,就是一个高级协程对象     任务对象 == 协程对象 == 特殊的函数      绑定回调 :task.add_done_callback(parse) #parse就是一个回调函数       parse的定义:         parse必须又一个参数,该参数表示的就是回调函数对应的任务对象         task.result(): 就是特殊函数的的返回值    事件循环对象 :可以让特殊函数内部的语句执行     该对象内部必须注册的是任务对象,当事件循环开启后其内部注册的任务对象就可以基于异步被执行   ps: 在特殊函数每部不可以出现不支持异步代码对应的模块 定义如下: import asyncio import time urls = [ 'http://127.0.0.1:5000/jay',

如何正确的在 Android 上使用协程 ?

China☆狼群 提交于 2019-12-01 20:38:09
前言 你还记得是哪一年的 Google IO 正式宣布 Kotlin 成为 Android 一级开发语言吗?是 Google IO 2017 。如今两年时间过去了,站在一名 Android 开发者的角度来看,Kotlin 的生态环境越来越好了,相关的开源项目和学习资料也日渐丰富,身边愿意去使用或者试用 Kotlin 的朋友也变多了。常年混迹掘金的我也能明显感觉到 Kotlin 标签下的文章慢慢变多了(其实仍然少的可怜)。今年的 Google IO 也放出了 Kotlin First 的口号,许多新的 API 和功能特性将优先提供 Kotlin 支持。所以,时至今日,实在找不到安卓开发者不学 Kotlin 的理由了。 今天想聊聊的是 Kotlin Coroutine 。虽然在 Kotlin 发布之初就有了协程,但是直到 2018 年的 KotlinConf 大会上,JetBrain 发布了 Kotlin1.3RC,这才带来了稳定版的协程。即使稳定版的协程已经发布了一年之余,但是好像并没有足够多的用户,至少在我看来是这样。在我学习协程的各个阶段中,遇到问题都鲜有地方可以求助,抛到技术群基本就石沉大海了。基本只能靠一些英文文档来解决问题。 关于协程的文章我看过很多,总结一下,无非下面几类。 第一类是 Medium 上热门文章的翻译,其实我也翻译过: 在 Android 上使用协程(一)

给协程加上同步互斥机制

纵然是瞬间 提交于 2019-12-01 18:44:52
前面一篇文章介绍了Linux内的同步互斥的概念、内核态和用户态Linux提供的同步/互斥接口。这里本文介绍下如何给协程加上同步、互斥机制。 简单说下协程coroutine: 参考文章 操作系统的课本中对进程、线程的定义:进程是最小的资源分配单位,线程是最小的调度单位。 随着互联网的飞速发展,互联网后台Server服务通常要面临高请求、高并发的挑战,一些业务Server通常要面临很高的网络IO请求。这也就是C10K问题。 现在对C10K问题的解决方案已经很成熟了,主要是 非阻塞IO+IO复用(epoll,select等)+网络事件驱动,另外再配合多进程/多线程。 对这种非阻塞IO+IO复用+网络事件驱动的解决方案,我们通常称为异步模式,与之想对应的是同步模式。 举个简单的例子: 对于服务srvA, 对于每个前端请求的逻辑如下: 收到前端Req,访问SrvB拉取数据,然后访问SrvC拉取数据,回包Rsp给前端 对于同步模式的解决方案: 对每个前端Req都要有一个线程或者进程来处理,直到回包给前端,逻辑中的网络访过程通常用阻塞模式;无论是用线程池/进程池或者每个请求产生一个进程或者线程来处理,当前端请求量大时,系统中存在大量进程/线程时,线程的调度、占用的内核资源都是比较严重的问题。 对于异步模式的解决方案: 利用IO复用+非阻塞IO,把会导致阻塞的操作转化为一个异步操作

腾讯测试开发面试总结

谁说胖子不能爱 提交于 2019-12-01 18:13:32
昨天接到了秋招以来的第一场面试,面试了腾讯的测试开发岗,自己感觉不是特别好,写此片博客只为总结下此次面试。 以前自己总觉得自己还不错,秋招应该可以找到一份工作,但此次面试对我犹如当头一棒!人不可骄傲,学习是一件终身去完成的事,不要以为自己学会了,就可以做自己可以做的事。记得有个故事:两个人在森林中遇到了一只老虎,那么老虎先吃谁呢?当然是吃跑的慢的。老虎就像这个社会的淘汰法则,你只要比别人慢,或者用程序员的来讲,你的技术只要比别人菜,你就有可能被吃。搞技术开发的,当问题来临时,解决不了,没有什么理由,菜就是原罪。 一、当下都有哪些爬虫技术、与反爬虫手段? 爬虫技术: 1、python自带的urlib2和urlib或者第三方模块request 此种方案适合简单的页面爬虫,比如爬取博客的文章等等,相对于其他的一些高级爬虫来讲,它没有异常处理与请求速度控制等,需要我们取用额外的代码去控制。 2、scrapy框架  相比urlib等基础爬虫,请求调度、异常处理都已经进行了基础的封装、而且有第三方的csrapy-redis模块支持分布式、使得程序员将重点放在了页面分析与规则编写上面。 3、python selenium和PhantomJS 具有很好的反爬虫技术、可以通过技术手段去模拟出和人非常类似的操作行为,缺点就是速度比较慢、但是爬虫一帮来讲对于速度的要请求不是很高、更注重的是数据的稳定

进程、线程、协程的关系

自作多情 提交于 2019-12-01 17:25:31
参考来源: https://blog.csdn.net/chengqiuming/article/details/80573288      https://www.cnblogs.com/guolei2570/p/8810536.html 协程不是进程,也不是线程,它就是一个函数,一个特殊的函数——可以在某个地方挂起,并且可以重新在挂起处继续运行。所以说,协程与进程、线程相比,不是一个维度的概念。 一个进程可以包含多个线程,一个线程也可以包含多个协程,也就是说,一个线程内可以有多个那样的特殊函数在运行。但是有一点,必须明确,一个线程内的多个协程的运行是串行的。如果有多核CPU的话,多个进程或一个进程内的多个线程是可以并行运行的,但是一个线程内的多个协程却绝对串行的,无论有多少个CPU(核)。这个比较好理解,毕竟协程虽然是一个特殊的函数,但仍然是一个函数。一个线程内可以运行多个函数,但是这些函数都是串行运行的。当一个协程运行时,其他协程必须挂起。 一 协程与进程、线程的比较 虽然说,协程与进程、线程相比不是一个维度的概念,但是有时候,我们仍然需要将它们做一番比较,具体如下: 1 协程既不是进程,也不是线程,协程仅仅是一个特殊的函数,协程跟他们就不是一个维度。 2 一个进程可以包含多个线程,一个线程可以包含多个协程。 3 一个线程内的多个协程虽然可以切换,但是这多个协程是串行执行的

【转】异步、并发、协程原理

拈花ヽ惹草 提交于 2019-12-01 17:05:47
Linux 操作系统在设计上将虚拟空间划分为用户空间和内核空间,两者做了隔离是相互独立的,用户空间给应用程序使用,内核空间给内核使用。 一、异步 应用程序和内核 内核具有最高权限,可以访问受保护的内存空间,可以访问底层的硬件设备。而这些是应用程序所不具备的,但应用程序可以通过调用内核提供的接口来间接访问或操作。所谓的常见的 IO 模型就是基于应用程序和内核之间的交互所提出来的。以一次网络 IO 请求过程中的 read 操作为例,请求数据会先拷贝到系统内核的缓冲区(内核空间),再从操作系统的内核缓冲区拷贝到应用程序的地址空间(用户空间)。而从内核空间将数据拷贝到用户空间过程中,就会经历两个阶段: 等待数据准备 拷贝数据 也正因为有了这两个阶段,才提出了各种网络 I/O 模型。 Unix/Linux的体系架构 同步和异步 同步(Synchronised)和异步(Asynchronized)的概念描述的是应用程序与内核的交互方式,同步是指应用程序发起 I/O 请求后需要等待或者轮询内核 I/O 操作完成后才能继续执行;而异步是指应用程序发起 I/O 请求后仍继续执行,当内核 I/O 操作完成后会通知应用程序,或者调用应用程序注册的回调函数。 阻塞和非阻塞 阻塞和非阻塞的概念描述的是应用程序调用内核 IO 操作的方式,阻塞是指 I/O 操作需要彻底完成后才返回到用户空间;而非阻塞是指 I

进程、线程、协程基本概念理解

三世轮回 提交于 2019-12-01 16:24:30
概述 最近接触一些进程、线程、协程、相关的东西,总是容易搞混淆,或者出错,专门想总结下这块的几个概念的问题! 进程 进程之间不共享任何状态 进程的调度由操作系统完成 每个进程都有自己独立的内存空间 进程间通讯主要是通过信号传递的方式来实现的,实现方式有多种,信号量、管道、事件等,任何一种方式的通讯效率都需要过内核,导致通讯效率比较低 由于是独立的内存空间,上下文切换的时候需要保存先调用栈的信息、cpu各寄存器的信息、虚拟内存、 以及打开的相关句柄等信息,所以导致上下文进程间切换开销很大,通讯麻烦。 线程 线程之间共享变量,解决了通讯麻烦的问题 对于变量的访问需要锁 线程的调度主要也是有操作系统完成 一个进程可以拥有多个线程,但是其中每个线程会共享父进程像操作系统申请资源,这个包括虚拟内存、文件等,由于是共享资源,所以创建线程所需要的系统资源占用比进程小很多,相应的可创建的线程数量也变得相对多很多。 线程时间的通讯除了可以使用进程之间通讯的方式以外还可以通过共享内存的方式进行通信,所以这个速度比通过内核要快很多。 另外在调度方面也是由于内存是共享的,所以上下文切换的时候需要保存的东西就像对少一些,这样一来上 下文的切换也变得高效。 协程 协程的调度完全由用户控制 一个线程可以有多个协程,用户创建了几个线程,然后每个线程都是循环按照指定的任务清单顺序完成不同的任务

Go多协程循环打印ABAC

£可爱£侵袭症+ 提交于 2019-12-01 15:58:27
前段时间有个题目,是要求Java多线程完成ABAC重复输出,要求是A线程值输出A,B线程只输出B,C线程只输出C, 可我不太会Java,就改用Go实现尝试一下, 当晚结束后改了1个多小时终于写完,也是对知识的补充理解了。 package main import ( "fmt" "sync" ) var wg sync.WaitGroup var n int var chA = make(chan int) var chB = make(chan int) var chC = make(chan int) func main() { fmt.Scan(&n) wg.Add(1)//增加进程任务 go send(n) wg.Wait()//用于等待该进程结束,直至wg.Done()运行次数等于wg.Add()增加的次数,同时避免time.Sleep的尴尬用法 } func send(n int) { go A(chA) go B(chB) go C(chC) chA <- 1 } func A(c chan int) { for {//for是为了保持运行 if count := <-c; count <= n { fmt.Print("A") if (count+1)%4 != 0 { chB <- count + 1 } else { chC <- count + 1 } }