并发系统有多种并发模型:
并行工作者模式:
在并行工作者模式中,委派者接收到任务(如刚才说讲的listen to request),分发给工作者完成任务(如handler request to work thread)。举个例子,如果在汽车工厂执行该模式,那么每个工人拿到图纸之后,该工人从头到尾负责整个产品。
并行工作者模型虽然容易理解,但也有缺点:
1.多个工作者需要共享数据,如果A工作者和B工作者共享了内存,那么每个工作者为了保持所操作的是最新数据版本,在每次调度之前都需要进行重新载入,刷新。
2.无法保证执行顺序,例如作业A在作业B之前被分配了,但是作业B在作业A之前被执行。
3.如果在存储中使用了阻塞的数据结构,那么同一时间只能允许一个线程来对数据结构进行操作,降低了并行性。
流水线模型(pipline):
如果说并发工作者像原始社会,缺乏分工,每个原始人拿到吃饭任务时,需要自己进行打猎,烹饪,保存等任务。
那么流水线模式就是现代社会,分工合作。有的原始人负责打猎,有的负责烹饪,有的负责保存。
分工才是这个社会的发展的原动力啊!!!
相比之前的并行工作者模型中,我们说到它如果在存储中使用了阻塞的数据结构,那么会降低并行性,流水线模式一般使用非阻塞IO,意味着,一旦工作者开始操作一个IO时(如等待网络连接),这个工作者不会一直等待IO的结束,IO速度很慢,大大浪费了CPU。此时他会让出CPU,等到IO完成之后再交由下一个工作者继续执行。
有了非阻塞IO,我们就可以界定工作者之间的工作范围。工作者尽可能工作到IO开始。
实际使用中,会有多条流水线,作业可能不沿着同一条流水线工作
那么,流水线工作者有何优点?
1.无需共享状态,工作者分工明确,无需考虑因并发而带来的共享数据的问题。例如:打猎的工作者和烹饪的工作者所使用的工具肯定不同,不是共享的。在实现单个工作者的时候就好像单个线程在处理工作
并发模型的选择:
如果作业本身就是并行,独立的就可以使用并行工作者模式。例如:在消息中间件场景中,我们常常使用kafka作为消息队列,producer塞消息进kafka,consumer取消息进行消费,consumer对每条消息消费的过程都是独立的。
如果作业本身不是并行,非独立的,就可以使用流水线工作模式(pipline)。例如:我们需要将一大批文件由小写改成大写,就可以分出3个步骤:1.读文件。2.改大小写。3.写文件。