您的当前位置:金沙澳门网址 > 一点资讯体育小 >

深入浅出那些你知道但不理解的并发模型

时间:2019-09-01

  阻塞IO:线程发起read操作,然后线程一直处于等待状态,直到IO操作完成,其实和上面的同步IO一样

  这种并发模型也是现在大多web后台开发的一种模式,尤其在Java中,应用程序启动后开启主线程,之后的请求都通过线程池技术来支撑并发。操作系统能保证当线程数小于等于cpu的个数时,让不同的线程运行在不同的cpu上,提高cpu的利用率,典型的如开源框架tomcat就是这种并发模型。

  不管任何并发模型其实都离不开的数据之间的交互,都需要通信,reactor,proactor这两种模型都是通过共享内存来进行通信,而actor强调的是通过通信来共享内存,actor强调的是没有共享,所有的线程之间都是消息传递来实现通信,数据交互,每一个actor就是一个线程,actor模型几十年前就已经出现,但因为受制于当时硬件的发展并没有被重视,随着多核时代的到来,actor模型开始有了用武之地,其中golang的goroutine,channel就是actor模型的一种实现,actor模型更适合多核编程,分布式编程,actor模型通过消息传递保证了内部数据的状态只会由自己修改,所以内部数据的处理不会涉及到锁,同步等问题,actor模型由以下几个组件组成:

  actor模型主要解决的是并发编程带来的锁,同步等复杂性,事实上MailBox中也有锁,同步的逻辑,试想一下,两个actor通过MailBox进行通信,一个写,一个读,就会有并发问题,actor模型也是做了更高层次的抽象,封装,我们从编程角度或者架构角度来看actor是实现通过消息传递来共享数据的模型设计,如下图:

  Proactor(主动器,提供完成事件的循环,进行事件分发处理后续逻辑)

  异步阻塞的做法是小明付帐以后,不会盯着老板做了,也不干其它事,老板做好了通知小明

  这种并发模型是应用程序启动后主进程会预先创建一些子进程出来,每来一个请求都会由一个子进程处理请求,这种模型会比较稳定,进程之间不干扰,也不会产生线程安全问题,同时也可以引入一些第三方的非线程安全的模块进来,但内存消耗较大,创建进程对内存的消耗会比较大,并且cpu在多个进程间来回切换开销也大,所以一般子进程不宜过多。典型的一些开源软件如Apache服务器在Apahce2.X之后新增了并行处理模块(MPM-Multi-Processing-Modules)Prefork就是这种并发模型

  进程的空间是独立,各个进程相互不干扰,每个进程拥有自己的进程内存,上下文环境,进程控制块,一个进程至少有一个或者多个线程。线程属于进程,线程要存在必须依赖于进程,线程共享进程的内存,但线程有自己的栈空间,能创建多少个线程也取决于进程内存的大小。

  这种模式将请求和处理分离,有专门的accept线程监听来自客户端的请求,请求到来后,也有专门的线程池处理读写任务,同时也有对应的业务线程池处理具体的业务逻辑,reactor模式虽然性能这么高,很多框架也在用,但reactor模式是同步的,主要体现在IO操作上会阻塞一直等待读写完成,如下图

  传统的基于多线程的client-server模式,客户端每发送一个请求,server就开启一个线程处理客户端请求,这种模式在并发量不是很大的情况下非常好,性能OK,编码也简单,但当并发量一旦突破上线,性能就会急剧下降,占用更多内存,cpu频繁的在多个线程间进行上下文切换,reactor模式是基于事件驱动的高并发模型,他把一次请求分成多个事件,比如(connect,read,write),每次事件发生的时候才去触发对应的处理器处理,reactor架构的主要由以下几个组件组成

  上面列了一些简单的比较,其实不同操作系统下有着一些较大差别,比如linux操作系统下,进程的创建和销毁其实和线程创建和销毁所需的代价差不多,具体需要在使用时深入调研。

  这种模式下真正实现IO的异步操作,不发发生阻塞,其实观察reactor和proactor并发模型,发现都是尽量减少线程在执行期间的阻塞,将原本在一条直线上完成的所有操作分割成多端,之间通过事件进行通信,reactor注册的是就绪事件,而proactor注册的是完成事件,由一个统一中央事件分发器进行管理,协作,这两种模型都依赖操作系统内核本身的支持,框架只是在操作系统本身的支持下调用操作系统的api实现了更高一层的封装,proactor模型如下图:

  proactor也是基于事件驱动的一种并发模型,但protacor是异步的,在IO操作时,proactor并发模型能够和操作系统之间解耦,由操作系统内核完成读写操作之后主动发送完成事件,这也是和reactor的最大区别,proactor由以下几个组件组成:

  同步非阻塞的做法是小明付帐后不会一直盯着老板,而是做其它事了,每隔一会来看看老板做好了没

  非阻塞IO:线程发起read操作,用户态切换到内核态,如果内核数据没有准备好,立刻返回一个错误,线程根据错误决定每隔一会轮询依次,当内核数据准备好后,会将数据从内核拷贝到用户态空间这个时候线程是一只处于等待状态的,也就是说第一阶段是非阻塞,第二阶段还是阻塞的

  end:如果你觉得本文对你有帮助的话,记得关注点赞转发,你的支持就是我更新动力。

  要了解各种并发模型思想,首先要了解什么是同步,什么是异步?什么是阻塞,什么是非阻塞?

  异步IO:线程发起read操作后,便可以做其他事了,操作系统数据准备好后(已经拷贝到用户态)会告诉线程。

  并发模型的核心是为了提高提高CPU利用率,提高服务器应对大量请求,海量数据处理的能力,单核CPU性能已经难以发展,各大厂商都在通过增加CPU个数来达到硬件处理能力的提高(摩尔定律),随之而来在编程语言方面衍生出各个模型(其实就是处理问题的思路)用来压榨硬件的性能,以使自己的系统并发能力得到提高。

  这种并发模型是在上面多进程的并发模型上演化而来,开启多个子进程,每个子进程下面又会开启多个线程,这种模式下并发承受压力会比单纯的多进程好许多,但在一些CPU密集型作业下未必会比多进程好,因为每一个进程下的多线程上下文不断切换的开销是非常大的,cpu本来就在多个进程间切换,现在又要在单个进程下的多个线程间切换,cpu大部分时间都在切换上下文了,真正用于计算的时间反而很少,因此影响了其性能,因此对于一些网页请求或者偏IO类的操作这种模式会比多进程的好上一些,典型的一些开源软件如Apache服务器在Apahce2.X之后新增了并行处理模块(MPM-Multi-Processing-Modules)Worker就是这种并发模型

  同步阻塞的做法是小明付帐后一直盯着老板制作烧鸡,直到完成才高兴的办其它事了

  同步IO:线程发起read操作,调用操作系统,这是会有一次用户态切换到内核态,内核开始等待数据到达,数据完成后,从内核拷贝到用户态空间,这个过程线程是一直等待状态的

  比较内容进程线程CPU,内存占用cpu和内存更多占用内存少,cpu切换简单数据共享合和同步数据共享比较复杂,需要通信,同步简单,应为数据是分开的数据共享简单,但同步比较复杂,需要锁操作创建和销毁进程是重量级的,创建和销毁都比较复杂线程是一种轻量级的进程,创建和销毁简单编程和调试复杂简单可靠想进程之间相互独立,不会影响,一个进程挂掉不会影响其它进程一个线程挂掉可能导致整个进程都over

  Reactor(反应器,循环运行事件,操作事件句柄的增删改查操作,分发事件)

  并行:一个人同一时间处理多件事的能力(显然一个人同一事件不能处理多件事,单核CPU不具备并行能力)

北大医疗鲁中医院 发财树之家 中国文化网 上海硕博公司 华恒生物官网 武汉未来科技城 百度
联系我们

400-500-8888

公司服务热线

金沙澳门网址