
Python并发编程
文章平均质量分 70
芳姐聊互联网职场
芳姐聊互联网职场
关注功能测试,(Python,Java)自动化测试,自动化办公,性能测试,安全测试,网络爬虫,系统架构知识,职场人生
个人工作经历:测试工程师,高级测试工程师,性能测试工程师,测试经理,测试讲师
展开
-
python并发编程:IO模型比较分析
经过上面的介绍,会发现non-blocking IO和asynchronous IO的区别还是很明显的。在non-blocking IO中,虽然进程大部分时间都不会被block,但是它仍然要求进程去主动的check,并且当数据准备完成以后,也需要进程主动的再次调用recvfrom来将数据拷贝到用户内存。blocking vs non-blocking:调用blocking IO会一直block住对应的进程直到操作完成,而non-blocking IO在kernel还准备数据的情况下会立刻返回。原创 2024-03-10 14:40:53 · 389 阅读 · 0 评论 -
python并发编程-多路复用IO
我们都知道,select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。O multiplexing这个词可能有点陌生,但是如果我说select/epoll,大概就都能明白了。有些地方也称这种IO方式为。原创 2024-03-09 09:19:13 · 913 阅读 · 0 评论 -
Python并发编程:非阻塞IO
从图中可以看出,当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是用户就可以在本次到下次再发起read询问的时间间隔内做其他事情,或者直接再次发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存(这一阶段仍然是阻塞的),然后返回。原创 2024-03-09 09:18:25 · 836 阅读 · 0 评论 -
python并发编程:阻塞IO
当用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段:准备数据。对于network io来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的udp包),这个时候kernel就要等待足够的数据到来。实际上,除非特别指定,几乎所有的IO接口(包括socket接口)都是阻塞型的。这给网络编程带来了一个很大的问题。如在调用recv(1024)的同时,线程将被阻塞,在此期间,线程将无法执行任何运算或响应任何的网络请求。原创 2024-03-06 20:20:35 · 482 阅读 · 0 评论 -
python并发编程:IO模型
再说一下IO发生时涉及的对象和步骤。对于一个network IO \(这里我们以read举例\),它会涉及到两个系统对象,一个是调用这个IO的process \(or thread\),另一个就是系统内核\(kernel\)。这两点很重要,因为这些io模型的区别就是在两个阶段上各有不同的情况。原创 2024-03-06 20:18:37 · 380 阅读 · 0 评论 -
Python并发编程:协程-gevent模块
Gevent是一个第三方库,可以轻松通过gevent实现并发同步或异步编程。在gevent中用到的主要模式是Greenlet,它是以C扩展模块形式接入Python的轻量级协程。Greenlet 全部运行在主程序操作系统进程的内部,但它们被协作式地调度。importgeventdefname)defname)上例gevent.sleep(2)模拟的是gevent可以识别的io阻塞而time.sleep(2)或其它的阻塞,gevent是不能直接识别的需要用下面一行代码,打补丁,就可以识别了。原创 2024-03-05 23:03:49 · 954 阅读 · 0 评论 -
Python并发编程:协程-greenlet模块
如果我们在单个线程内有20个任务,要想实现在多个任务之间切换,使用yield生成器的方式过于麻烦(需要先得到初始化一次的生成器,然后再调用send。单线程里的这20个任务的代码通常会既有计算操作又有阻塞操作,完全可以在执行任务1时遇到阻塞,就利用阻塞的时间去执行任务2.。如此,才能提高效率,这就用到了Gevent模块。greenlet只是提供了一种比generator更加快捷的切换方式,当切到一个任务执行时如果遇到io,那就原地阻塞,仍然是没有解决遇到io自动切换来提升效率的问题。原创 2024-03-05 23:00:10 · 642 阅读 · 0 评论 -
Python并发编程:协程介绍
对于单线程下,我们不可避免程序中出现io操作,但如果我们能在自己的程序中(即用户程序级别,而非操作系统级别)控制单线程下的多个任务在一个任务遇到io阻塞时就切换到另外一个任务去计算,这样就保证了该线程能够最大限度地处于就绪态,即随时都可以被CPU执行的状态,相当于我们在用户程序级别将自己的io操作最大限度的隐藏起来,从而可以迷惑操作系统,让其看到:该线程好像是一直在计算,io比较少,从而更多的将CPU的执行权限分配给我们的线程。'''任务1:接收数据,处理数据''''''任务2:生产数据'''原创 2024-03-04 08:34:55 · 1047 阅读 · 0 评论 -
Python并发编程:多线程-进程池与线程池
基于多进程或多线程实现并发的套接字通信,这样的实现方式存在的缺陷是:服务开启的进程数或线程数都会随着并发的客户端数目的增多而增多,这会对服务端主机带来巨大的压力,甚至于不堪重负而瘫痪,于是我们必须对服务端开启的进程数或线程数加以控制,让机器在一个自己可以承受的范围内运行,这就是进程池或线程池的用途,例如进程池,就是用来存放进程的池子,本质还是基于多进程,只不过是对开启进程的数目加以限制。原创 2024-03-04 08:33:03 · 1135 阅读 · 0 评论 -
Python并发编程:多线程-线程queue
【代码】Python并发编程:多线程-线程queue。原创 2024-03-03 20:45:46 · 427 阅读 · 0 评论 -
Python并发编程:多线程-信号量,Event,定时器
对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。如果有线程等待一个Event对象,而这个Event对象的标志为假,那么这个线程将会被一直阻塞至标志为真。信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,信号量同一时间可以有5个任务拿到锁去执行,如果说互斥锁是合租房屋的人去抢一个厕所,那么信号量就相当于一群路人争抢公共厕所,公共厕所所有多个坑位,这意味着同一时间可以有多个人上公共厕所,但公共厕所容纳的人数是一定的,这便是信号量的大小。原创 2024-03-03 20:44:32 · 926 阅读 · 0 评论 -
Python并发编程:多线程-死锁现象与递归锁
上面的例子如果使用RLock代替Lock,则不会发生死锁,二者的区别是:递归锁可以连续acquire多次,而互斥锁只能acquire一次。所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁。解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,Python提供了可重入锁RLock。原创 2024-03-02 07:15:00 · 629 阅读 · 0 评论 -
Python并发编程:多线程-GIL全局解释器锁
解释器的代码是所有线程共享,所以垃圾回收线程也可能访问到解释器的代码而去执行,这就导致了一个问题:对于同一个数据100,可能线程1执行x=100的同时,而垃圾回收执行的是回收100的操作,解决这种问题没有声明高明的方法,就是加锁处理,如下图的GIL,保证Python解释器同一时间只能执行一个任务的代码。最后:问题是很明朗了,GIL与LOCK是两把锁,保护的数据不一样,前者是解释器级别的(当然保护的就是解释器级别的数据,比如垃圾回收的数据),后者是保护用户自己开发的应用程序的数据,很明显GIL。原创 2024-03-02 07:00:00 · 968 阅读 · 0 评论 -
Python并发编程:多线程-守护线程
无论是进程还是线程,都遵循:守护XXX会等待主XXX运行完毕后被销毁需要强调的是:运行完毕并非终止运行12。原创 2024-03-01 09:00:22 · 492 阅读 · 0 评论 -
Python并发编程:多线程-Thread对象的其它属性和方法
12345678910Thread实例对象的方法# isAlive():返回线程是否活动的# getName():返回线程名# setNmae():设置线程名threading模块提供的一些方法:# threading.currentThread(): 返回当前的线程变量# threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。原创 2024-03-01 08:58:59 · 427 阅读 · 0 评论 -
Python并发编程:多线程与多进程的区别
1. 在主进程下开启线程123456789fromimportThreaddef执行结果如下:几乎是t.start()的同时就将线程开启了,然后先打印出了hello,证明线程的创建开销极小12hello主进程2、在主进程下开启子进程1234567891011fromimport执行结果如下:p.start()将开启进程的信号发给操作系统后,操作系统要申请内存空间,让好拷贝父进程地址空间到子进程,开销远大于线程12主进程hello。原创 2024-02-29 08:32:04 · 919 阅读 · 0 评论 -
Python并发编程:多线程-开启线程的两种方式
multiprocess模块完全模仿了threading模块的接口,二者在使用层面,有很大的相似性。原创 2024-02-29 08:30:00 · 443 阅读 · 0 评论 -
Python并发编程:多线程-线程理论
在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于CPU),而一条流水线必须属于一个车间,一个车间的工作过程是一个进程,车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一条流水线。所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是CPU上的执行单位。原创 2024-02-27 22:37:48 · 574 阅读 · 0 评论 -
Python并发编程:多进程-生产者消费者模型
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题,生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。生产者指的是生产数据的任务,消费者指的是处理数据的任务,在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。2、引入生产者消费者模型为了解决的问题是。原创 2024-02-27 22:36:36 · 1649 阅读 · 0 评论 -
Python并发编程:多进程-队列
进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的。原创 2024-02-26 20:21:08 · 557 阅读 · 0 评论 -
Python并发编程:多进程-互斥锁
进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱,如下:123456789101112131415161718192021fromimportosimporttimedefforinisisisisdone28451isdone28450isdone。原创 2024-02-26 20:19:25 · 1300 阅读 · 0 评论 -
Python并发编程:多进程-守护进程
主进程创建子进程,然后将该进程设置成守护自己的进程,守护进程就好比皇帝身边的老太监,皇帝已死老太监就跟着殉葬了。原创 2024-02-25 10:56:18 · 716 阅读 · 0 评论 -
Python并发编程:多进程-join方法
进程只要start就会在开始运行了,所以p1-p4.start()时,系统中已经有四个并发的进程了,而我们p1.join()是在等p1结束,没错p1只要不结束,主线程就会一直卡在原地,这也是问题的关键,join是让主线程等,而p1-p4仍然是并发执行的,p1.join的时候,其余p2,p3,p4仍然在运行,等p1.join结束,可能p2,p3,p4早已经结束了,这样p2.join,p3.join,p4.join直接通过检测,无需等待,所以4个join花费的总时间仍然是耗费时间最长的那个进程运行的时间。原创 2024-02-25 10:54:51 · 1564 阅读 · 0 评论