1.什么是进程?什么是线程?
进程是表示资源分配的基本单位,又是调度运行的基本单位。
例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,
包括各种表格、内存空间、磁盘空间、I/O设备等。然后,把该进程放
人进程的就绪队列。进程调度程序选中它,为它分配CPU以及其它有关资源,该进程才真正运行。
线程是进程中执行运算的最小单位,如果把进程理解为在逻辑上操作系统所完成的任务,
那么线程表示完成该任务的许多可能的子任务之一。例如,假设用户启子任务;在产生
工资单报表的过程中,用户又可以输人数据库查询请求,这又是一个子任务。
多线程就像是火车上的每节车厢,而进程就是火车。
2.多进程和多线程的区别?
- 数据共享、同步:
1). 数据共享复杂,需要用IPC;数据是分开的,同步简单
2). 因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂
各有优势 - 内存、CPU
1). 占用内存多,切换复杂,CPU利用率低
2). 占用内存少,切换简单,CPU利用率高
线程占优 - 创建销毁、切换
1). 创建销毁、切换复杂,速度慢
2). 创建销毁、切换简单,速度很快
线程占优 - 编程、调试
1). 编程简单,调试简单
2). 编程复杂,调试复杂
进程占优 - 可靠性
1). 进程间不会互相影响
2). 一个线程挂掉将导致整个进程挂掉
进程占优 - 分布式
1). 适应于多核、多机分布式;如果一台机器不够,扩展到多台机器比较简单
2). 适应于多核分布式
进程占优
3.进程之间的通信方式以及优缺点?
管道, 信号量, 信号, 消息队列, 共享内存, 套接字
4.线程之间的通信方式?
锁机制:包括互斥锁、条件变量、读写锁
信号量机制(Semaphore)
信号机制(Signal)
5.什么时候用多线程?什么时候用多进程?
1)需要频繁创建销毁的优先用线程
2)需要进行大量计算的优先使用进程
3)可能要扩展到多机分布的用进程,多核分布的用线程
1. 协程概念
协程,又称微线程,纤程,英文名Coroutine。协程的作用,是在执行函数A时,可以随时中断,
去执行函数B,然后中断继续执行函数A(可以自由切换)。但这一过程并不是函数调用(没有调
用语句),这一整个过程看似像多线程,然而协程只有一个线程执行*******。
2. 协程优势
- 执行效率极高,因为子程序切换(函数)不是线程切换,由程序自身控制,
没有切换线程的开销。所以与多线程相比,线程的数量越多,协程性能的优势越明显。 - 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在控制共
享资源时也不需要加锁,因此执行效率高很多。
说明:协程可以处理 IO 密集型程序的效率, 但是处理 CPU 密集型不是它的长处,
如要充分发挥 CPU 利用率可以结合多进程 + 协程。
协程案例:
import threading
from urllib.request import urlopen
from urllib.error import HTTPError
import gevent
from gevent import monkey
from concurrent.futures import ThreadPoolExecutor, wait
from mytimeit import timeit
monkey.patch_all()
def get_page_length(url):
try:
urlObj = urlopen(url)
except HTTPError as e:
print("捕获失败.....")
else:
pageContent = urlObj.read()
# print("%s长度为%d" %(url, len(pageContent)))
# 做实验, 访问本地url, 因为获取网络的url与网速有关(网速不稳定)
urls = ['file:///usr/share/doc/HTML/en-US/index.html', 'file:///usr/share/doc/HTML/en-US/index.html',
'file:///usr/share/doc/HTML/en-US/index.html', 'file:///usr/share/doc/HTML/en-US/index.html', ] * 30000
@timeit
def use_gevent():
gevents = [gevent.spawn(get_page_length, url) for url in urls]
gevent.joinall(gevents)
print("协程执行结束.....")
@timeit
def use_thread():
threads = []
for url in urls:
t = threading.Thread(target=get_page_length, args=(url,))
t.start()
threads.append(t)
[thread.join() for thread in threads]
if __name__ == '__main__':
use_thread()
use_gevent()