Python 多进程、多线程(一)和IO多路复用

本章内容简介

1) Python2.7和Python3.5 多继承的区别:

2) IO多路复用

3) 多进程,多线程(一)

一. Python2.7和Python3.5 多继承的区别

  1. Python2.7多继承时,A类名如果继承object类,表示是新式类,继承关系和Python3.5是相同的,如下图:

 2. Python2.7多继承时,A类名如果不继承任何类,表示经典类,继承关系如下图:

 3. Python的作用域

  • 作用域 :Python和JavaScript没有块级作用域,Java和c#里有:

比如: Python里可以打印出name;

if 1 == 1:name = 12print(name)

Python的作用域,在函数里表现;

函数中的参数,不被外部调用,比如:

def f1():name = 'hailong'return name
obj = f1()
print(obj)
print(name)

实例中,函数里定义的name,虽然被执行过了,但是外部还是不能获取到,函数内部的变量name; 这个执行结果,会报错。

4. 为了更好的理解作用域,我们再写个lambd表达式的实例:

li = [lambda :x for x in range(5)]
print(li[3]())

相当于下面的代码:

li = []
for x in range(5):def a():return xli.append(a)print(li[3]())

代码解析:

  li 是一个列表 ,列表里的元素是五个函数内存地址,如果执行,将被调用;我们给li加了索引值,然后括号,就是执行对应的函数;

函数执行结果:无论索引值输入4以内的几(索引不能超出range值),结果都是4,因为每个函数的返回值都是for循环后x最后赋的值;

二. IO多路复用

IO多路复用是什么?

  • 1.1 多路复用概念:

监听多个描述符(文件描述符(windows下暂不支持)、网络描述符)的状态,如果描述符状态改变 则会被内核修改标志位,进而被进程获取进而进行读写操作

  • 1.2 多路复用两种触发方式:

水平触发(Level Triggered):

将就绪的文件描述符告诉进程后,如果进程没有对其进行IO操作,那么下次调用select()和poll()的时候将再次报告这些文件描述符,所以它们一般不会丢失就绪的消息,但是会增加消耗

边缘触发(Edge Triggered):

只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,理论上边缘触发的性能要更高一些,但是代码实现相当复杂。

  • 1.3 阻塞/非阻塞 模式:

阻塞:

如果阻塞模式则等待数据

非阻塞:

如果非阻塞模式有数据返回数据、无数据直接返回报错

  • 1.4 I/O模型:

同步I/O:

一问一答 等待数据(阻塞模式)或 不管有没有数据都返回(非阻塞模式)

异步I/O:

用户进程问完之后干别的处理结果出来之后告知用户进程

  • 1.5 selec/poll/epoll

相同点和不同点图解

Python IO复用之select

格式:

rList,wList,eList = select.select(argv1,argv2,argv3,timeout)

参数:

argv1 标准输入 监听序列中句柄,连接有变化时,则将变化句柄返回至rList

argv2 如果监听序列中句柄发生变化,有数据变化时, 则将变化句柄返回至wList

argv3 如果监听序列中句柄有错误时 则将错误句柄返回到eList

timeout 设置阻塞时间,如果为2那么将阻塞2s,如果不设置则默认一直阻塞

select 使用之读写分离,实例:

server端代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Liuhailong
# Email : 13552658435@126.comimport socket
import selectsk = socket.socket()
sk.bind(("127.0.0.1",8009))
sk.listen(5)inputs = [sk,]
outputs = []
while True:rlist,wlist,e = select.select(inputs,outputs,[],1)print(len(inputs),len(rlist),len(wlist),len(outputs))for r in rlist:if r == sk:conn,address = r.accept()inputs.append(conn)conn.sendall(bytes('hello',encoding='utf-8'))else:print("==============")try:data = r.recv(1024)if not data:raise Exception("断开链接")else:outputs.append(r)except Exception as e:inputs.remove(r)for w in wlist:w.sendall(bytes("response",encoding="utf-8"))outputs.remove(w)

client端代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Liuhailong
# Email : 13552658435@126.comimport socketsk = socket.socket()
sk.connect(("127.0.0.1", 8009,))
data = sk.recv(1024)
print(data)
while True:inp = input(">>>")sk.sendall(bytes(inp,encoding='utf-8'))print(sk.recv(1024))
sk.close()

代码解析:

  这个实例,利用select的参数特性,实现了读写分离,io复用;

执行结果:   开启多个客户端窗口,测试io复用,每个窗口都可以执行自己的输入,显示效果如下:

三. 多线程、多进程

1、多线程简介

多线程编程技术可以实现代码并行性,优化处理能力,同时功能的更小划分可以使代码的可重用性更好。Python中threading和Queue模块可以用来实现多线程编程。
2、详解
  1)、线程和进程

  进程(有时被称为重量级进程)是程序的一次执行。每个进程都有自己的地址空间、内存、数据栈以及其它记录其运行轨迹的辅助数据。操作系统管理在其上运行的所有进程,并为这些进程公平地分配时间。进程也可以通过fork和spawn操作来完成其它的任务,不过各个进程有自己的内存空间、数据栈等,所以只能使用进程间通讯(IPC),而不能直接共享信息。

线程(有时被称为轻量级进程)跟进程有些相似,不同的是所有的线程运行在同一个进程中,共享相同的运行环境。它们可以想像成是在主进程或“主线程”中并行运行的“迷你进程”。线程有开始、顺序执行和结束三部分,它有一个自己的指令指针,记录自己运行到什么地方。线程的运行可能被抢占(中断)或暂时的被挂起(也叫睡眠)让其它的线程运行,这叫做让步。一个进程中的各个线程之间共享同一片数据空间,所以线程之间可以比进程之间更方便地共享数据以及相互通讯。线程一般都是并发执行的,正是由于这种并行和数据共享的机制使得多个任务的合作变为可能。实际上,在单CPU的系统中,真正的并发是不可能的,每个线程会被安排成每次只运行一小会,然后就把CPU让出来,让其它的线程去运行。在进程的整个运行过程中,每个线程都只做自己的事,在需要的时候跟其它的线程共享运行的结果。多个线程共同访问同一片数据不是完全没有危险的,由于数据访问的顺序不一样,有可能导致数据结果的不一致的问题,这叫做竞态条件。而大多数线程库都带有一系列的同步原语,来控制线程的执行和数据的访问。
  2)、使用线程
  (1)全局解释器锁(GIL)
       Python代码的执行由Python虚拟机(也叫解释器主循环)来控制。Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行。虽然 Python 解释器中可以“运行”多个线程,但在任意时刻只有一个线程在解释器中运行。
       对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。在多线程环境中,Python 虚拟机按以下方式执行:a、设置 GIL;b、切换到一个线程去运行;c、运行指定数量的字节码指令或者线程主动让出控制(可以调用 time.sleep(0));d、把线程设置为睡眠状态;e、解锁 GIL;d、再次重复以上所有步骤。
        在调用外部代码(如 C/C++扩展函数)的时候,GIL将会被锁定,直到这个函数结束为止(由于在这期间没有Python的字节码被运行,所以不会做线程切换)编写扩展的程序员可以主动解锁GIL。
  (2)退出线程
       当一个线程结束计算,它就退出了。线程可以调用thread.exit()之类的退出函数,也可以使用Python退出进程的标准方法,如sys.exit()或抛出一个SystemExit异常等。不过,不可以直接“杀掉”("kill")一个线程。
        不建议使用thread模块,很明显的一个原因是,当主线程退出的时候,所有其它线程没有被清除就退出了。另一个模块threading就能确保所有“重要的”子线程都退出后,进程才会结束。
  (3)Python的线程模块
       Python提供了几个用于多线程编程的模块,包括thread、threading和Queue等。thread和threading模块允许程序员创建和管理线程。thread模块提供了基本的线程和锁的支持,threading提供了更高级别、功能更强的线程管理的功能。Queue模块允许用户创建一个可以用于多个线程之间共享数据的队列数据结构。
       避免使用thread模块,因为更高级别的threading模块更为先进,对线程的支持更为完善,而且使用thread模块里的属性有可能会与threading出现冲突;其次低级别的thread模块的同步原语很少(实际上只有一个),而threading模块则有很多;再者,thread模块中当主线程结束时,所有的线程都会被强制结束掉,没有警告也不会有正常的清除工作,至少threading模块能确保重要的子线程退出后进程才退出。
3、多线程threading模块

Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。

import threading
import timedef f1(arg,t=None):if t:t._delete()time.sleep(3)print(arg)# for i in range(10):
#     f1(i)  # 单进程,单线程
for i in range(6):t1 = threading.Thread(target=f1,args=(i,))  # 多线程t1.start() # 不代表当前线程会被立即执行# t1.join()
print('end')

更多方法:

  • start            线程准备就绪,等待CPU调度
  • setName      为线程设置名称
  • getName      获取线程名称
  • setDaemon   设置为后台线程或前台线程(默认)
                       如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
                        如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
  • join              逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
  • run              线程被cpu调度后自动执行线程对象的run方法
import threading
import timeclass MyThread(threading.Thread):def __init__(self,num):threading.Thread.__init__(self)self.num = numdef run(self):#定义每个线程要运行的函数print("running on number:%s" %self.num)time.sleep(3)if __name__ == '__main__':t1 = MyThread(1)t2 = MyThread(2)t1.start()t2.start()

线程锁(Lock、RLock)

由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,当多个线程同时修改同一条数据时可能会出现脏数据,所以,出现了线程锁 - 同一时刻允许一个线程执行操作。

未使用锁:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import timegl_num = 0def show(arg):global gl_numtime.sleep(1)gl_num +=1print(gl_num)for i in range(10):t = threading.Thread(target=show, args=(i,))t.start()print ('main thread stop')

使用线程锁:

#!/usr/bin/env python
#coding:utf-8import threading
import timegl_num = 0lock = threading.RLock()def Func():lock.acquire()global gl_numgl_num +=1time.sleep(1)print (gl_num)lock.release()for i in range(10):t = threading.Thread(target=Func)t.start()

信号量(Semaphore)

互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。

import threading,timedef run(n):semaphore.acquire()time.sleep(1)print("run the thread: %s" %n)semaphore.release()if __name__ == '__main__':num= 0semaphore  = threading.BoundedSemaphore(5) #最多允许5个线程同时运行for i in range(20):t = threading.Thread(target=run,args=(i,))t.start()

转载于:https://www.cnblogs.com/liuhailong-py-way/p/5661117.html

day10 多进程、多线程(一)相关推荐

  1. 利用进化算法+多进程/多线程来优化SVM中的两个参数:C和Gamma

    该案例展示了如何利用进化算法+多进程/多线程来优化SVM中的两个参数:C和Gamma. 在执行本案例前,需要确保正确安装sklearn,以保证SVM部分的代码能够正常执行. 本函数需要用到一个外部数据 ...

  2. linux 多进程 多线程的选择

    关于多进程和多线程,教科书上最经典的一句话是"进程是资源分配的最小单位,线程是CPU调度的最小单位",这句话应付考试基本上够了,但如果在工作中遇到类似的选择问题,那就没有这么简单了 ...

  3. 多进程多线程GDB调试 (转)

    多进程多线程GDB调试   一.线程调试指南:   1. gdb attach pid 挂载到调试进程  2. gdb$ set scheduler-locking on 只执行当前选定线程的开关 3 ...

  4. 浅谈多进程多线程的选择(转)

    关于多进程和多线程,教科书上最经典的一句话是"进程是资源分配的最小单位,线程是CPU调度的最小单位",这句话应付考试基本上够了,但如果在工作中遇到类似的选择问题,那就没有这么简单了 ...

  5. linux c多进程多线程,linux下的C\C++多进程多线程编程实例详解

    linux下的C\C++多进程多线程编程实例详解 1.多进程编程 #include #include #include int main() { pid_t child_pid; /* 创建一个子进程 ...

  6. 进程 线程 多进程 多线程 父进程 子进程

    1. 进程定义: 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ...

  7. Python实现多进程/多线程同时下载单个文件

    功能描述: 使用多进程/多线程同时下载单个文件,可以自定义文件地址.进程/线程数量. 主要思路: 获取文件大小,使用多个进程/线程分别下载一部分,最后再把这些文件拼接起来. 参考代码: 运行结果: - ...

  8. linux线程并不真正并行,多核时代:并行程序设计探讨(3)——Windows和Linux对决(多进程多线程)...

    并行程序设计探讨(3)--Windows和Linux对决(多进程多线程) 前面的博文经过分析总结,最后得出两种并行技术:多进程多线程.多机协作.对于多进程和多线程来说,最有代表性且最常见的的莫过于Wi ...

  9. 多CPU 多核CPU | 多进程 多线程 | 并行 并发

    文章目录 区分 多CPU && 多核CPU CPU缓存 并行 && 并发 多CPU && 多核CPU | 多进程 && 多线程 | 并行 ...

  10. python多进程多线程,多个程序同时运行

    python 多线程 多进程同时运行 多任务要求 python 基础语法 python 文件目录操作 python 模块应用 开发工具 pycharm 实现方法 多任务的实现可以用进程和线程来实现 进 ...

最新文章

  1. 学习java一定会用到的应用软件
  2. html动画怎么隐藏,JQuery操作div隐藏和显示的4种动画
  3. Visual Studio 项目目录下的bin目录和 obj目录
  4. 一些实用的mysql语句(不断积累更新)
  5. ad16自动布线设置规则_PCB设计的十大误区——那些年,我们一起遵守的规则
  6. Tomcat数据源总结
  7. Spring Boot之注册servlet三大组件
  8. spring data jpa 的 in 查询 Specification 实现
  9. ad软件one pin错误是啥意思_Unity3D 4.5 软件安装教程
  10. aauto的listview(类似于C#的datagrid) 支持文件拖拽获取名单
  11. html5兼容QQ浏览器,【QQ浏览器5.1】发布 HTML5兼容性测试
  12. 异常:Handler sending message to a Handler on a dead thread
  13. 数字1的ASCII值是多少
  14. 电子秤芯片——人体秤芯片及方案设计
  15. Android曲线水波纹动画,Android水波纹显示进度效果,很炫
  16. 从程序员到项目经理(25):对绩效考核的吐槽
  17. 英语口语九十九之每日十句口语
  18. CF-133A - HQ9+
  19. win cmd 打开D盘
  20. 大sd卡 裂开了,写保护掉了。重新装好后,被写保护的解决办:

热门文章

  1. Xcode安装及卸载
  2. maltab利用plot画图后更改线条颜色
  3. 在一个递增有序链表中插入新结点并保持链表递增顺序不变
  4. Linux. C open创建文件,c-为什么open()用错误的权限创建我的文件?
  5. oracle 安装的提示ntp,oracle rac 安装 PRVG-13606 ntp 同步报错解决过程
  6. java 压缩包添加文件,如何在Java中向现有zip文件添加条目?
  7. 关于QT中对窗口中某个widget建类
  8. mysql sbr_腾讯云数据库团队:MySQL语句复制(SBR)的缺陷列举
  9. alter table 加多个字段_Vue 组件设计 - table不需要封装
  10. 当前最快的实例分割模型:YOLACT 和 YOLACT++