并发服务器
3种具有代表性的并发服务器端实现模型和方法:
-
多进程服务器
- 通过创建多个进程提供服务
-
多路复用服务器
- 通过捆绑并统一管理I/O对象提供服务
-
多线程服务器
- 通过生成与客户端等量的线程提供服务
进程
-
基础概念
- 进程是操作系统资源分配的基本单位
- 一个进程是某种类型的一个活动,它有程序、输入、输出以及状态
- 每个进程都拥有各自的程序
- 一个程序运行了两遍,相当于两个进程
- 每个进程都具有独立的内存空间 (通信复杂)
-
进程间通信
- 进程间通信(
IPC,InterProcess Communication
)是指在不同进程之间传播或交换信息。 - IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、
Socket
、Streams
等。其中Socket
和Streams
支持不同主机上的两个进程IPC
- 进程间通信(
-
多进程缺点
- 创建进程的过程会带来一定的开销
- 进程间数据交换,需要特殊的
IPC
技术
上下文切换
-
基础概念
- 为了分时使用CPU,需要“上下文切换”过程:任务从保存到再加载的过程
- 运行程序前需要将相应任务(进程、线程等)信息读入内存,如果运行进程A后需要紧接着运行进程B,则需要将进程A的相关信息移出内存,并读入进程B相关信息。
线程
-
基础概念
- 线程是处理器任务调度和执行的基本单位
- 为了保持多进程的优点,同时在一定程度上克服其缺点
- 引入“线程”,一种“轻量级进程”
- 多个线程共享数据区和堆,为了保持多条代码执行流而隔开了栈区域
-
线程优点
- 线程的创建和上下文切换比进程快 (不需要切换数据区和堆)
- 线程间交换数据无需特殊技术 (利用数据区和堆交换数据)
-
线程间通信
- 共享内存: 隐式通信,显式同步
- 消息传递:显式通信,隐式同步
线程在进程内创建并运行
- 进程: 在操作系统构成单独执行流的单位
- 线程:在进程构成单独执行流的单位
多线程一定快吗
- 答案: 否。( 并发执行累加操作不超过百万次时,速度会比串行执行累加操作慢)
- 原因:线程有创建和上下文切换的开销
多个线程同时访问同一变量引发的问题
-
线程分时使用CPU,为何会出现同时访问变量的情况
-
此处的“ 同时访问 ” 并非指严格意义上的同一时间
并发(concurrency):把CPU时间分成若干段(CPU时间片),多个线程指令被快速的轮换执行,使得在
宏观
上具有多个线程同时执行的效果,但在微观上并不是同时执行的,同一时刻只能有一条指令执行并行(parallel):指在同一时刻,有多条指令在
多个处理器上
同时执行。无论从微观还是从宏观来看,二者都是一起执行的。 -
如图所示,假设线程A、B都要执行将变量值num加1的操作
理想情况,线程A将num
增加到100
后,线程B再访问num
,将其增加至101
;
但是需注意值的增加方式,值的增加需要CPU运算完成,变量num中的值不会自动增加。
即num++
被解析为num = num+1
;
这个操作不具备原子性,可分为3步;
-
线程读取
num
的值并传递到CPU
-
CPU
运算,获得num 加 1后的结果 -
将结果写回变量
num
- 问题出现: 线程A在第3步操作前,即还未将结果写回
num
,线程B通过切换得到CPU资源,此时线程B读取到的num
值仍为99,结果是线程B将num
值改为100,然后线程A将自己的运算结果100再次写回变量num
- 虽然线程A、B都各做了一次加1运算,结果却出人意外,因此多线程需注意线程安全问题
- 解决:同步(
Synchronization
),线程访问变量num
时应阻止其他线程访问,直至自己完成运算。
- 问题出现: 线程A在第3步操作前,即还未将结果写回
线程同步
- 线程同步用于解决线程访问顺序引发的问题
- 同时访问同一内存空间值更改问题 (num++)
- 需指定同一内存空间的线程执行顺序问题(读写数据顺序)
线程 句柄 线程ID
- 线程属于操作系统管理的资源,因此线程创建会伴随内核对象的创建,并为了引用内核对象而返回句柄
- 句柄的整数值在不同进程中可能出现重复,线程ID则不会
- 可通过句柄区分同一进程中的线程,通过线程ID区分操作系统创建的所有线程
用户模式 内核模式
- 用户模式:应用程序的运行模式,禁止访问物理设备,限制访问的内存区域
- 内核模式:操作系统的运行模式,不受限制
线程 操作系统 应用程序
- 实际创建线程的是操作系统,创建线程请求是由应用程序的函数调用完成
- 所以程序运行过程中,需在用户模式和内核模式之间切换
- 用户模式同步
- 内核模式同步
注意
:
- 如您发现本文档中有错误的地方,
- 或者您发现本文档中引用了他人的资料而未进行说明时,请联系我进行更正。
- 转载或使用本文档时,请作说明。
- 非常感谢
:)