python并发编程相关概念总结
1、简述计算机操作系统中的“中断”的作用?
中断是指在计算机执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的时间处理程序。
待处理完毕后又返回原来被中断处继续执行或调度新的进程执行的过程。
当遇到IO操作时或一个进程运行时间过长或被更高的优先级的进程替代时出现中断。有利于合理利用有限的系统资源,提高程序运行效率。
2、简述计算机内存中的“内核态”和“用户态”;
处于用户态的程序只能访问用户空间,而处于内核态的程序可以访问用户空间和内核空间。
当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。
当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。此时处理器在特权级最低的(3级)用户代码中运行。
用户态切换到内核态的3种方式:
1、系统调用:这是用户态进程主动要求切换到内核态的一种方式
2、异常
3、外围设备的中断
3、进程间通信方式有哪些?
进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。
IPC的方式通常有:管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。
4、简述你对管道、队列的理解;
管道:通常指无名管道
它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。
它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。
它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。
队列:是消息的链接表。一个消息队列由一个标识符(即队列ID)来标识。
消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。 队列和管道都是将数据存放于内存中,而队列是基于“管道+锁”实现的。
5、请列举你知道的进程间通信方式;
1.管道(无名管道):速度慢,容量有限,只有父子进程能通讯。它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。
2.FIFO(命名管道):任何进程间都能通讯,但速度慢,它是一种文件类型。
3.消息队列:是消息的链接表,存放在内核中。消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除,所以要注意第一次读的时候,要考虑上一次没有读完数据的问题。容量受到系统限制。消息队列可以实现消息的随机查询
4.信号量:信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
5.共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存
信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
6、什么是同步I/O,什么是异步I/O?
Stevens给出的定义(其实是POSIX的定义)是这样子的:
A synchronous I/O operation causes the requesting process to be blocked until that I/O operationcompletes;
An asynchronous I/O operation does not cause the requesting process to be blocked;
同步IO:当程序发生IO操作时,会将进程阻塞,直到IO操作完成才能继续执行后面的代码。如:blocking IO,non-blocking IO,IO multiplexing。
异步IO:进程不会发生阻塞。如:asynchronous IO。
7、请问multiprocessing模块中的Value、Array类的作用是什么?举例说明它们的使用场景
使用Value或者Array把数据存储在一个共享的内存表中,用于实现进程间共享状态。
Value( typecode, arg1, … argN, lock )
在共享内容中常见ctypes对象。typecode要么是包含array模块使用的相同类型代码(如’i’,’d’等)的字符串,要么是来自ctypes模块的类型对象(如ctypes.c_int、ctypes.c_double等)。
所有额外的位置参数arg1, arg2 ….. argN将传递给指定类型的构造函数。lock是只能使用关键字调用的参数,如果把它置为True(默认值),将创建一个新的锁定来包含对值的访问。
如果传入一个现有锁定,比如Lock或RLock实例,该锁定将用于进行同步。如果v是Value创建的共享值的实例,便可使用v.value访问底层的值。例如,读取v.value将获取值,而赋值v.value将修改值。 RawValue( typecode, arg1, … ,argN)
同Value对象,但不存在锁定。 Array( typecode, initializer, lock )
在共享内存中创建ctypes数组。typecode描述了数组的内容,意义与Value()函数中的相同。initializer要么是设置数组初始大小的整数,要么是项目序列,其值和大小用于初始化数组。lock是只能使用关键字调用的参数,意义与Value()函数中相同。
如果a是Array创建的共享数组的实例,便可使用标准的python索引、切片和迭代操作访问它的内容,其中每种操作均由锁定进行同步。对于字节字符串,a还具有a.value属性,可以吧整个数组当做一个字符串进行访问。 RawArray(typecode, initializer )
同Array对象,但不存在锁定。当所编写的程序必须一次性操作大量的数组项时,如果同时使用这种数据类型和用于同步的单独锁定(如果需要的话),性能将得到极大的提升。
# 进程间共享状态,当然尽最大可能防止使用共享状态,但最终有可能会使用到.
# 1-共享内存
# 可以通过使用Value或者Array把数据存储在一个共享的内存表中
from multiprocessing import Process,Value,Array
import time def f(n, a, name):
time.sleep(1)
n.value = name * name
for i in range(len(a)):
a[i] = -i process_list = []
if __name__ == '__main__':
num = Value('d',0.0) # d表示一个双精浮点类型
arr = Array('i',range(10)) # i表示一个带符号的整型
for i in range(10):
p = Process(target=f,args=(num, arr, i))
p.start()
process_list.append(p)
for j in process_list:
j.join()
print(num.value)
print(arr[:])
# 更加灵活的共享内存可以使用multiprocessing.sharectypes模块
https://blog.csdn.net/winterto1990/article/details/48106505
8、请问multiprocessing模块中的Manager类的作用是什么?与Value和Array类相比,Manager的优缺点是什么?
使用Value或者Array把数据存储在一个共享的内存表中。
Manager()返回一个manager类型,控制一个server process,可以允许其它进程通过代理复制一些python objects。
支持:list,dict,Namespace,Lock,Semaphore,BoundedSemaphore,Condition,Event,Queue,value,Array ;
Manager 提供了多进程环境中共享数据的使用的方案, 共享数据可以支持跨进程, 甚至跨机器访问, 以网络通信的方式实现(eg: unix socket, tpc),一个 manager 实例控制一个 server 进程(manager 自己创建的后台进程,对用户透明), 该 server 负责管理共享数据. 其他进程则是用户业务创建的,它们可以通过代理方式来访问 manager 自带 server 的共享数据. 代理可以理解为一个网络通道, 业务进程 和 manager server 进程通信交互数据, 由于server 单线程, 对业务进程通信请求FIFO的方式来处理数据, 因此保证了操作行为的可预期性(当然如果业务进程希望锁定数据, 可以通过代理的 Lock 锁机制来实现).
manger的的优点是可以在poor进程池中使用,缺点是windows下环境下性能比较差,因为windows平台需要把Manager.list放在if name='main'下,而在实例化子进程时,必须把Manager对象传递给子进程,否则lists无法被共享,而这个过程会消耗巨大资源,因此性能很差。
https://www.cnblogs.com/shengyang17/p/8987075.html
9、写一个程序,包含十个线程,子线程必须等待主线程sleep 10秒钟之后才执行,并打印当前时间;
import time
from threading import Thread, currentThread def task():
print("current time:", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) if __name__ == "__main__":
t_l = []
for i in range(10): # 开启10个线程
t = Thread(target=task)
t_l.append(t)
for t in t_l:
time.sleep(10)
t.start()
10、写一个程序,包含十个线程,同时只能有五个子线程并行执行;
import time
import random
from threading import Thread, currentThread, Semaphore def task():
sm.acquire()
print("%s is running" % currentThread().getName())
time.sleep(random.randint(1, 3))
sm.release() if __name__ == "__main__":
sm = Semaphore(5)
for i in range(10):
t = Thread(target=task, name="线程%s" % i)
t.start()
11、写一个程序,要求用户输入用户名和密码,要求密码长度不少于6个字符,且必须以字母开头,如果密码合法,则将该密码使用md5算法加密后的十六进制概要值存入名为password.txt的文件,超过三次不合法则退出程序;
import hashlib
import re def register():
i = 1
while i <= 3:
username = input("username:").strip()
password = input("password:").strip()
if len(password) >= 6 and re.search("\A[a-zA-Z]", password):
m = hashlib.md5()
m.update(password.encode("utf-8"))
md5 = m.hexdigest()
with open("password.txt", "a", encoding="utf-8") as f:
f.write("%s,%s" % (username, md5))
print("注册成功!")
break
else:
print("密码长度不少于6个字符,且必须以字母开头")
i += 1 if __name__ == "__main__":
register()
12、写一个程序,使用socketserver模块,实现一个支持同时处理多个客户端请求的服务器,要求每次启动一个新线程处理客户端请求;
服务端:
# 基于socketserver的进程间并发通信
import socketserver class Server(socketserver.BaseRequestHandler):
"""服务端"""
def handle(self): # 必须定义一个名为handle的方法
"""处理与客户端的交互"""
while True: # 循环接收和发送消息
msg = self.request.recv(1024) # 收消息
if not msg:
break
print("from %s: %s" % (self.client_address, msg.decode())) # 客户端地址信息和消息
self.request.send(msg.upper()) # 发送消息给客户端 if __name__ == "__main__":
server_addr = ("127.0.0.1", 8080)
server = socketserver.ThreadingTCPServer(server_addr, Server) # 实现多线程的socket通话
print("server starting.....")
server.serve_forever() # 当一个客户端链接断开后继续循环接收其他客户端链接
客户端:
class Client:
"""客户端"""
def __init__(self, ip, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.connect((ip, port)) def handle_msg(self):
"""发送、接收消息"""
while True:
msg = input(">>>").strip()
if not msg:
break
self.sock.send(msg.encode())
data = self.sock.recv(1024)
print("from server:", data.decode()) if __name__ == "__main__":
client = Client("127.0.0.1", 8080)
print("server connecting.....")
client.handle_msg()
https://www.cnblogs.com/xiajie/p/5250675.html
https://www.cnblogs.com/progor/p/8617042.html
python并发编程相关概念总结的更多相关文章
- Python并发编程-多进程
Python并发编程-多进程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.多进程相关概念 由于Python的GIL全局解释器锁存在,多线程未必是CPU密集型程序的好的选择. ...
- Python并发编程06 /阻塞、异步调用/同步调用、异步回调函数、线程queue、事件event、协程
Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件event.协程 目录 Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件 ...
- Python并发编程__多进程
Python并发编程_多进程 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大 ...
- Python并发编程的几篇文章
Python几种并发实现方案的性能比较 http://www.elias.cn/Python/PyConcurrency?from=Develop.PyConcurrency python并发编程 h ...
- Python并发编程之深入理解yield from语法(八)
大家好,并发编程 进入第八篇. 直到上一篇,我们终于迎来了Python并发编程中,最高级.最重要.当然也是最难的知识点--协程. 当你看到这一篇的时候,请确保你对生成器的知识,有一定的了解.当然不了解 ...
- 自学Python之路-Python并发编程+数据库+前端
自学Python之路-Python并发编程+数据库+前端 自学Python之路[第一回]:1.11.2 1.3
- Python并发编程二(多线程、协程、IO模型)
1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...
- Python并发编程一(多进程)
1.背景知识(进程.多道技术) 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一 ...
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...
随机推荐
- Java的HashMap和HashTable(转)
来源:http://www.cnblogs.com/devinzhang/archive/2012/01/13/2321481.html 1. HashMap 1) hashmap的数据结构 Has ...
- tomcat7 开机自启动(转)
转自 http://blog.csdn.net/rainyspring4540/article/details/51861079 环境:win7 tomcat7 开机自启动: 使用管理员打开命令提示 ...
- cf1051F. The Shortest Statement(最短路)
题意 题目链接 题意:给出一张无向图,每次询问两点之间的最短路,满足$m - n <= 20$ $n, m, q \leqslant 10^5$ Sol 非常好的一道题. 首先建出一个dfs树. ...
- c++编写递归函数char *itostr (int n,char *string),该函数将整数n转换为十进制表示的字符串。
#include<iostream> #include<stdio.h> using namespace std; ; char *itostr (int n,char *St ...
- MyDebugeer 一个简单调试器的实现
学习的是网上的帖子,所以就不贴源码了. 整个程序以调试循环为主体,实现了启动调试,继续执行,内存查看,读取寄存器值,显示源代码,断点的设置.查看.删除,三种单步执行:StepIn.StepOver.S ...
- Redis安装配置及在Python上的应用
最近在使用Kazoo(开源电话系统) API时,一次请求的处理需要调用几次API,只为了得到一个name和id的对应关系,耗时非常大,开始想使用一种简单的实现,直接将对应关系保存到静态类的静态变量中, ...
- log4j 配置文件 (XML/.properties)
xml: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configurat ...
- BZOJ 1229: [USACO2008 Nov]toy 玩具
BZOJ 1229: [USACO2008 Nov]toy 玩具 标签(空格分隔): OI-BZOJ OI-三分 OI-双端队列 OI-贪心 Time Limit: 10 Sec Memory Lim ...
- linux怎么进home目录下
可以使用cd命令,cd命令的功能是切换到指定的目录: 命令格式:cd [目录名] 有几个符号作为目录名有特殊的含义: “/”代表根目录.“..”代表上一级目录.“~”代表HOME目录.“-”代表前一目 ...
- 1.redis 安装
1.https://redis.io/download. 2. $ wget http://download.redis.io/releases/redis-3.2.9.tar.gz $ .tar.g ...