基本的并发编程模型

基于进程的并发

基本模型

在TCP服务器编程中,多进程并发服务器通常由主进程负责连接的建立,然后fork出子进程,负责该连接剩下的行为,直到关闭。

关于多进程并发服务器有几点重要的内容:

通常服务器会运行很长时间,因此必须要包括一个SIGCHLD处理程序,来回收僵死子进程的资源。因为当SIGCHLD处理程序执行时,SIGCHLD信号是阻塞的,而Unix信号是不排队的,所以SIGCHLD处理程序必须准备好回收多个僵死子进程的资源。

父进程在fork调用后,将连接交给子进程处理,父子进程必须关闭他们各自不用的fd拷贝,对父进程尤为重要。

因为套接字的文件表表项中的引用计数,直到父子进程的fd都关闭了,到客户端的连接才会终止。

优劣

进程有独立的地址空间,既是优点也是缺点,这样一来一个进程不可能不小心覆盖另一个进程的虚拟存储器,另一方面,独立的地址空间使得进程共享状态信息变得更加困难。

基于进程的并发能力毕竟有限,想想系统下成百上千个进程的情况下,系统还能运转多快,更别说几万了。

基于I/O多路复用的并发

何为多路复用

虽然了解I/O多路复用,但一直以来,对这个名字很好奇,什么叫多路复用?为什么称为IO多路复用?

通过查看维基上的定义算是有了一个初步的认识,以下是在维基中摘录的部分介绍:

多路复用(Multiplexing,又称“多工”)是一个通信和计算机网络领域的专业术语,通常表示在一个信道上传输多路信号或数据流的过程和技术。因为多路复用能够将多个低速信道整合到一个高速信道进行传输,从而有效地利用了高速信道。通过使用多路复用,通信运营商可以避免维护多条线路,从而有效地节约运营成本。

多路复用的抽象模型

首先,各个低速信道的信号通过多路复用器(MUX,多工器)组合成一路可以在高速信道传输的信号。在这个信号通过高速信道到达接收端之后,再由分路器(DEMUX,解多工器)将高速信道传输的信号转换成多个低速信道的信号,并且转发给对应的低速信道。查看原文请点击

反过来看I/O多路复用,就是在一个线程中,处理多路I/O。对应于多路复用的原则,线程处理能力必须快,I/O需要尽可能的拆分成小的单元,每个单元尽量短的占用线程的时间,如果某个I/O处理单元长时间占用线程的处理时间,就会导致其他I/O得不到及时的处理。

I/O多路复用的基本思想

比如我的程序需要从多个I/O上等待数据到来并读取

pipe fd1

tcp socket1 fd2

tcp socket2 fd3

udp socket fd4

那么定义一个数组{fd1,fd2,fd3,fd4}存储好,并通知内核,我对这几个fd的输入事件感兴趣,此时内核会说你等着吧,等他们谁有数据了我会通知你,然后你就睡眠了。

当某个fd有数据到达可读时,内核会立即通知你,嘿,有数据来了,快醒了。于是你赶快醒来,找到哪个fd有数据,然后接收处理,处理完了,一轮结束继续告知内核感兴趣的事件,然后睡眠。

linux支持I/O多路复用的系统调用有select、poll、epoll。

I/O多路复用优缺点

I/O多路复用可以用于事件驱动的编程,事件驱动设计,比基于进程的设计给了程序员给多的多程序行为的控制。例如一个并发服务器,需要为某些客户端提供特殊化的服务,基于事件驱动的设计,可以在流程里面有选择的处理。而基于进程的设计,需要在fork进程之前,选择子进程的行为,如果特殊化的服务比较多,基于进程的设计处理起来是很困难的。

基于I/O多路复用的服务器是运行在单一进程上下文中,因此每个逻辑流都能访问该进程的全部地址空间,使得流之间共享数据变得很容易。

基于I/O多路复用的服务器在GDB调试时要比多进程方便。

基于驱动设计常常比基于进程的设计要高效的多,因为他们并不需要进程上下文切换。

事件驱动设计的一个明显的缺点是编码复杂,随着并发颗粒度(每个逻辑流在每个时间片上执行的指令数量)减小,复杂性还会上升。并发粒度控制不好,很容易导致忙于处理某个逻辑流,其他流得不到处理。

基于线程的并发

基于线程的逻辑流结合了基于进程和基于I/O多路复用的的流的特性。同进程一样,线程由内核自动调度,并且内核通过一个整数ID来识别线程。同基于I/O多路复用的流一样,多个线程运行在单一进程的上下文中,因此共享这个进程虚拟地址空间的整个内容,包括他的代码、数据、堆、共享库和打开的文件。

基本多线程模型

整个模型类似与基于多进程的设计,主线程不断的等待连接请求,然后创建一个线程处理该请求。

这个模型中有个微妙的问题,主线程建立某一新连接的fd,如果直接传递给子线程,那么很有可能在子线程处理前,主线程建立了另一个连接,并更新了fd,那么不幸的结果就是,现在两个线程在同一个描述符上执行输入输出。以下是示例代码:

1 connfd = accept(listenfd, &clientaddr, &clientlen);
2 pthread_create(&tid, NULL, thread, &connfd);

另一个问题是在线程例程中避免存储器泄露,要么显示回收内存,要么必须分离内存。

基于预线程化的生产者-消费者模型

服务器由一个主线程和一组工作者线程构成,主线程不断的接受来自客户端的连接请求,并将得到的连接描述符放在一个有限缓冲区中。每一个工作者线程反复的从共享缓冲区中取出描述符,为客户端服务,然后等待下一个描述符。

I/O多路复用不时编写事件驱动程序的唯一方法,上述模型实际上也是一个事件驱动服务器,带有主线程和工作线程的简单状态机。

多线程并发编程中需要考虑的一些问题参考《深入理解计算机系统》12.7节,如果你有更好的书,记得推荐给我哟。

高级并发编程

参考NGINX并发处理模型的设计

基本的并发编程模型

时间: 2024-11-07 01:22:22

基本的并发编程模型的相关文章

Java多线程-并发编程模型

以下内容转自http://ifeve.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B/: 并发系统可以采用多种并发编程模型来实现.并发模型指定了系统中的线程如何通过协作来完成分配给它们的作业.不同的并发模型采用不同的方式拆分作业,同时线程间的协作和交互方式也不相同.这篇并发模型教程将会较深入地介绍目前(2015年,本文撰写时间)比较流行的几种并发模型. 并发模型与分布式系统之间的相似性 本文所描述的并发模型类似于分布式系统中使

IO复用、多进程和多线程三种并发编程模型

I/O复用模型 I/O复用原理:让应用程序可以同时对多个I/O端口进行监控以判断其上的操作是否可以进行,达到时间复用的目的.在书上看到一个例子来解释I/O的原理,我觉得很形象,如果用监控来自10根不同地方的水管(I/O端口)是否有水流到达(即是否可读),那么需要10个人(即10个线程或10处代码)来做这件事.如果利用某种技术(比如摄像头)把这10根水管的状态情况统一传达到某一点,那么就只需要1个人在那个点进行监控就行了,而类似与select或epoll这样的多路I/O复用机制就好比是摄像头的功能

4.并发编程模型

并发系统可以采用多种并发编程模型来实现.并发模型指定了系统中的线程如何通过协作来完成分配给它们的作业.不同的并发模型采用不同的方式拆分作业,同时线程间的协作和交互方式也不相同.这篇并发模型教程将会较深入地介绍目前(2015年,本文撰写时间)比较流行的几种并发模型. 并发模型与分布式系统之间的相似性 本文所描述的并发模型类似于分布式系统中使用的很多体系结构.在并发系统中线程之间可以相互通信.在分布式系统中进程之间也可以相互通信(进程有可能在不同的机器中).线程和进程之间具有很多相似的特性.这也就是

【专家坐堂】四种并发编程模型简介

本文来自网易云社区 概述 并发往往和并行一起被提及,但是我们应该明确的是"并发"不等同于"并行" ?       并发 :同一时间 对待 多件事情 (逻辑层面) ?       并行 :同一时间 做(执行) 多件事情 (物理层面) 并发可以构造出一种问题解决方法,该方法能够被用于并行化,从而让原本只能串行处理的事务并行化,更好地发挥出当前多核CPU,分布式集群的能力. 但是,并发编程和人们正常的思维方式是不一样的,因此才有了各种编程模型的抽象来帮助我们更方便,更不容

大数据技术之_16_Scala学习_11_客户信息管理系统+并发编程模型 Akka+Akka 网络编程-小黄鸡客服案例+Akka 网络编程-Spark Master Worker 进程通讯项目

第十五章 客户信息管理系统15.1 项目的开发流程15.2 项目的需求分析15.3 项目的界面15.4 项目的设计-程序框架图15.5 项目的功能实现15.5.1 完成 Customer 类15.5.2 完成显示主菜单和退出软件功能15.5.3 完成显示客户列表的功能15.5.4 完成添加客户的功能15.5.5 完成删除客户的功能15.5.6 完善退出确认功能15.5.7 完善删除确认功能15.5.8 完成修改客户的功能第十六章 并发编程模型 Akka16.1 Akka 的介绍16.2 Acto

程序员必知的七种并发编程模型

1.线程与锁线程与锁模型有很多众所周知的不足,但仍是其他模型的技术基础,也是很多并发软件开发的首选. 2.函数式编程 函数式编程日渐重要的原因之一,是其对并发编程和并行编程提供了良好的支持.函数式编程消除了可变状态,所以从根本上是线程安全的,而且易于并行执行. 3.Clojure之道——分离标识与状态 编程语言Clojure是一种指令式编程和函数式编程的混搭方案,在两种编程方式上取得了微妙的平衡来发挥两者的优势. 4.actor actor模型是一种适用性很广的并发编程模型,适用于共享内存模型和

Scala-Unit7-Scala并发编程模型AKKA

一.Akka简介 Akka时spark的底层通信框架,Hadoop的底层通信框架时rpc. 并发的程序编写很难,但是Akka解决了spark的这个问题. Akka构建在JVM平台上,是一种高并发.分布式.并且容错的应用工具包: Akka使用Scala语言编写,同时它提供了Scala和Java的开发接口,Akka可以开发一些高并发的程序. 二.Akka的Acor模型 A卡卡处理并发的方法基于actor模型,在基于actor的系统中,所有事物都是actor(类似于Java的万物皆对象): actor

Scala 学习 (七) 并发编程模型Akka

一,Akka简介 二,Akka中的Actor模型 三,Akka实战案例之HelloActor 四,Akka实战案例之PingPong 五,案例基于 Actor 的聊天模型 正文 一,Akka简介 写并发程序很难.程序员不得不处理线程.锁和竞态条件等等,这个过程很容易出错,而且会导致程序代码难以阅读.测试和维护.Akka 是 JVM 平台上构建高并发.分布式和容错应用的工具包和运行时.Akka 用 Scala 语言写成,同时提供了 Scala 和 JAVA 的开发接口 二,Akka中的Actor模

并发编程模型基础

并发编程中,有两个关键问题:线程之间如何通信及线程之间如何同步. 通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种,共享内存和消息传递. 在共享内存的并发模型里,线程之间共享程序的公共状态,通过读写内存中的公共状态进行隐式通信:在消息传递的并发模型李,线程之间没有公共状态,线程之间必须通过发送消息来显示进行通信. 同步是指程序中用于控制不同线程间操作发生相对顺序的机制.在共享内存并发模型中,同步是显式进行的,程序员必须显式指定某个方法或某个代码需要在线程之间互斥执行