1. 并发、并行、同步、异步、阻塞、非阻塞
实际举例说明:
问题 - 喝茶
情况: 开水没有,水壶要洗,茶壶茶杯要洗;火生类, 茶叶也有了。怎么办?
所需时间:
洗水壶: 3
灌凉水: 1
洗茶壶: 3
洗茶杯: 3
拿茶叶: 1
泡茶: 1
烧开水: 30
并发版本:
老赵(cpu1):
办法1: 洗水壶,灌凉水, 放在火上;等待水烧开的时间里, 洗水壶,洗茶杯,拿茶叶;等水开了,泡茶喝。
总用时: 3+1+30+1 = 35
办法2: 先做好一些准备工作, 洗水壶,洗茶壶茶杯,拿茶叶;也切就绪,灌水烧水;坐等水开了泡茶喝。
总用时: 3+3+3+1+30+1 = 41
办法3: 洗净水壶,灌上凉水,放在火上,坐等水开;水开之后, 急急忙忙找茶叶,洗茶壶茶杯,泡茶喝。
总用时: 3+1+30+3+3+1 = 41
并行版本:
老赵(cpu1):洗好水壶,灌上凉水,放在火上
老李(cpu2):洗茶壶
老李(cpu2):洗茶壶
老谢(cpu3):洗茶杯
总用时: 31
例子:
小乐爱喝茶,废话不说,煮开水。
出场人物:小乐,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
1 小乐把水壶放到火上,立等水开。(同步阻塞)
—— 小乐觉得自己有点傻
2 小乐把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
—— 小乐还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出呜呜~~~~的噪音。
3 小乐把响水壶放到火上,立等水开。(异步阻塞)
—— 小乐觉得这样傻等意义不大
4 小乐把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
—— 小乐觉得自己聪明了。
所谓同步异步,只是对于水壶而言。
普通水壶,同步;响水壶,异步。
虽然都能干活,但响水壶可以在自己完工之后,提示小乐水开了。这是普通水壶所不能及的。
同步只能让调用者去轮询自己(情况2中),造成小乐效率的低下。
所谓阻塞非阻塞,仅仅对于小乐而言。
—— 立等的小乐,阻塞;看电视的小乐,非阻塞。
情况1和情况3中小乐就是阻塞的,媳妇喊他都不知道。
虽然3中响水壶是异步的,可对于立等的小乐没有太大的意义。
所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。
2. I/O多路复用介绍(select, poll, epoll)
1)阻塞I/O(blocking I/O)
2)非阻塞I/O (nonblocking I/O)
3)I/O复用(select 和poll) (I/O multiplexing)
4)信号驱动I/O (signal driven I/O (SIGIO))
5)异步I/O (asynchronous I/O (the POSIX aio_functions))
前四种都是同步,只有最后一种才是真正的异步IO。
阻塞I/O:
简介:进程会一直阻塞,直到数据拷贝完成
描述:应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。
如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返回成功指示。

非阻塞IO:
简介:非阻塞IO通过进程反复调用IO函数(多次系统调用,并马上返回);在数据拷贝的过程中,进程是阻塞的;
描述:我们把一个SOCKET接口设置为非阻塞就是告诉内核,当所请求的I/O操作无法完成时,
不要将进程睡眠,而是返回一个错误。这样我们的I/O操作函数将不断的测试数据是否已经准备好,
如果没有准备好,继续测试,直到数据准备好为止。在这个不断测试的过程中,会大量的占用CPU的时间。
IO复用:
简介:主要是select和epoll;对一个IO端口,两次调用,两次返回,
比阻塞IO并没有什么优越性;关键是能实现同时对多个IO端口进行监听;
描述:I/O复用模型会用到select、poll、epoll函数,这几个函数也会使进程阻塞,
但是和阻塞I/O所不同的的,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,
多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数。
信号驱动IO:
简介:两次调用,两次返回;
描述:首先我们允许套接口进行信号驱动I/O,并安装一个信号处理函数,进程继续运行并不阻塞。
当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。