第8章 多线程程序设计技术
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
7
图8-1 并发模型工作原理图 8
将一个接受的连接递交给另外一个套接字的方法很简
单,只要利用accept()函数的返回值即可,程序代码如下:
SOCKET m_socket,
//the socket for waiting
connection
AcceptSocket; //the socket for accepting a
第8章 多线程程序设计技术
8.1 服务器线程模型 8.2 多线程应用环境 8.3 线程基本操作函数 8.4 线程同步 8.5 并发线程模型服务器设计 8.6 完成端口服务器设计 小结
1
通过前面几章的学习,读者已经基本掌握了在主要几 种网络协议下,进程之间进行网络数据通信的程序设计的 基本方法。然而,实际的网络服务程序的开发设计要复杂 得多,需要运用一些辅助技术,例如处理并发服务的多线 程技术、快速开发网络程序的封装技术等。因此,从本章 开始将陆续介绍一些网络编程的相关技术。
3
8.1 服务器线程模型
网络服务器设计可以采用两种线程模型,即串行模型 和并发模型。
串行模型采用单个线程等待客户端的请求,当请求到 来时,该线程醒来并处理请求,这种模型可以应用于简单 的服务器程序,其优点是服务器接受的请求比较少,而且 请求能被很快地处理。
4
串行模型的缺点也十分明显,当多个客户端同时向服务器 发出请求时,这些请求必须依次被接受,并且后一个请求 总是在前一个请求处理完毕后才能被接受。然而,在网络 服务应用程序工作中,随时可能面临为多个不同时间到达 的请求提供服务的局面(互联网上几乎所有服务程序都面临 这样的问题),显然,这种局面是串行模型无法应对的。
在C/S工作模式下,总是少量的服务器为众多的、数量 不可预测的多个客户端服务。客户端服务请求的到达不但 难以预测,而且具有显著的并发性,为此服务器必须设计 成能够服务于并发请求,且具有伸缩性。
2
本章将从多线程概念入手,介绍可伸缩服务,继而介绍线 程同步的方法以及完成端口技术。本章内容多使用在服务 器端,因此在程序设计的方法介绍上更加侧重于服务器编 程。
connection
…
AcceptSocket=accept(m_socket,NULL,NULL);
程序中的m_socket用于主线程监听网络连接,
Aቤተ መጻሕፍቲ ባይዱceptSocket用于接收一个m_socket已经接受的网络连接,
更详细的代码可以参考8.5节中的程序示例。
9
8.2 多线程应用环境
多线程是指程序中包含多个执行流,即在一个程序中 可以同时运行多个不同的执行路径(线程)来执行不同的任 务,也就是说,允许单个程序创建多个并行执行的子程序 来完成各自的任务。例如,一个公司里有很多各司其职的 职员,那么可以认为这个正常运作的公司就是一个进程, 而公司里的职员就是线程。公司(进程)作为一个功能整体 完成某一宏观任务,而员工在这个整体框架下,各负其责 完成自己的工作。
多线程程序设计通过分割、组织工作任务,合理利用 了任务的阻塞时间,有效地提高了程序的运行效率,但是 本质上它并没有提升硬件设备本身的性能,因此并不是任 何场合都适用,归纳起来它能够适合以下几种编程环境:
11
(1) 通过网络(例如,与Web服务器、数据库或远程对 象)进行通信;
(2) 执行需要较长时间因而可能导致 UI 冻结的本地操 作;
(3) 区分各种优先级的任务; (4) 提高应用程序启动和初始化的性能。 进行多线程程序设计时应当注意:线程越多,占用内 存也越多,线程之间需要协调和管理,对共享资源的访问 会相互影响,太多的线程会导致控制复杂和系统不稳定(线 程之间的切换会耗费大量的CPU计算时间)。这些都是使用 多线程时的不利因素,因此应当慎重。
为了解决串行模型存在的问题,可以使用并发模型。 并发模型使用单个线程等待客户端请求,当请求到来时, 创建新线程来处理请求。等待客户请求的线程继续等待另 一个客户端请求,新线程完成请求处理。当新线程处理完 客户端请求后,随即退出。
5
由于并发模型为每个客户端都会创建一个新的线程,客户 端请求能够很快地被处理,并且每个客户端请求都有自己 的线程,因此服务效率要明显好于串行模型,且基于并发 模型的服务器程序具有良好的伸缩性,当升级硬件时,服 务器程序的性能可以得到提高。
下面以WinSock的面向连接服务器编程为例,说明并 发模型的工作原理(如图8-1所示)。
首先安排主线程作为监听线程(执行路径),创建一个 套接字监听客户端的连接请求。当有一个连接请求到达时, 让主线程创建一个新的套接字。
6
监听套接字将接受的客户端连接递交给新的套接字,然后 创建一个线程并由该线程提供具体的服务,而主线程继续 监听来自客户端的连接请求。线程服务结束后,释放资源。 当主线程再次收到下一个连接请求时(前面线程的服务不一 定结束),再创建一个新套接字接收连接请求,并创建相应 线程提供服务。依次类推,从而实现服务器的并行服务。 这样不但满足了少量服务器端为多个客户端服务的需求, 也为各个用户数据传输的独立性提供了保证,可以说是对 并发服务请求问题的初步解决(更深层次的问题讨论参见8.6 节)。
10
一个公司至少得有一个职员,同理,一个进程至少包含一 个线程(事实上目前几乎已经没有单线程的网络商业应用软 件),浏览器就是一个很好的多线程的例子。在浏览器中, 用户可以同时完成下载Java小应用程序或图像、滚动页面、 播放动画和声音、打印文件等,就是基于多线程技术实现 的。多线程的使用可以提高CPU的利用率,这是因为在多 线程程序中,当一个线程必须等待时,CPU可以运行其他 的线程而不是等待,从而大大提高了程序的效率。
12
8.3 线程基本操作函数
线程在操作系统中的存在有多种状态,好比人的生老 病死,相对应于初始态、可运行态、阻塞/非可运行态和死 亡态等四种状态。程序设计中,进入或改变这些状态需要 一些函数的支持,学会运用这些函数也就掌握了多线程的 编程技术。Windows为用户提供了完备的基本线程操作, 下面具体来看一下这些基本线程操作函数。
图8-1 并发模型工作原理图 8
将一个接受的连接递交给另外一个套接字的方法很简
单,只要利用accept()函数的返回值即可,程序代码如下:
SOCKET m_socket,
//the socket for waiting
connection
AcceptSocket; //the socket for accepting a
第8章 多线程程序设计技术
8.1 服务器线程模型 8.2 多线程应用环境 8.3 线程基本操作函数 8.4 线程同步 8.5 并发线程模型服务器设计 8.6 完成端口服务器设计 小结
1
通过前面几章的学习,读者已经基本掌握了在主要几 种网络协议下,进程之间进行网络数据通信的程序设计的 基本方法。然而,实际的网络服务程序的开发设计要复杂 得多,需要运用一些辅助技术,例如处理并发服务的多线 程技术、快速开发网络程序的封装技术等。因此,从本章 开始将陆续介绍一些网络编程的相关技术。
3
8.1 服务器线程模型
网络服务器设计可以采用两种线程模型,即串行模型 和并发模型。
串行模型采用单个线程等待客户端的请求,当请求到 来时,该线程醒来并处理请求,这种模型可以应用于简单 的服务器程序,其优点是服务器接受的请求比较少,而且 请求能被很快地处理。
4
串行模型的缺点也十分明显,当多个客户端同时向服务器 发出请求时,这些请求必须依次被接受,并且后一个请求 总是在前一个请求处理完毕后才能被接受。然而,在网络 服务应用程序工作中,随时可能面临为多个不同时间到达 的请求提供服务的局面(互联网上几乎所有服务程序都面临 这样的问题),显然,这种局面是串行模型无法应对的。
在C/S工作模式下,总是少量的服务器为众多的、数量 不可预测的多个客户端服务。客户端服务请求的到达不但 难以预测,而且具有显著的并发性,为此服务器必须设计 成能够服务于并发请求,且具有伸缩性。
2
本章将从多线程概念入手,介绍可伸缩服务,继而介绍线 程同步的方法以及完成端口技术。本章内容多使用在服务 器端,因此在程序设计的方法介绍上更加侧重于服务器编 程。
connection
…
AcceptSocket=accept(m_socket,NULL,NULL);
程序中的m_socket用于主线程监听网络连接,
Aቤተ መጻሕፍቲ ባይዱceptSocket用于接收一个m_socket已经接受的网络连接,
更详细的代码可以参考8.5节中的程序示例。
9
8.2 多线程应用环境
多线程是指程序中包含多个执行流,即在一个程序中 可以同时运行多个不同的执行路径(线程)来执行不同的任 务,也就是说,允许单个程序创建多个并行执行的子程序 来完成各自的任务。例如,一个公司里有很多各司其职的 职员,那么可以认为这个正常运作的公司就是一个进程, 而公司里的职员就是线程。公司(进程)作为一个功能整体 完成某一宏观任务,而员工在这个整体框架下,各负其责 完成自己的工作。
多线程程序设计通过分割、组织工作任务,合理利用 了任务的阻塞时间,有效地提高了程序的运行效率,但是 本质上它并没有提升硬件设备本身的性能,因此并不是任 何场合都适用,归纳起来它能够适合以下几种编程环境:
11
(1) 通过网络(例如,与Web服务器、数据库或远程对 象)进行通信;
(2) 执行需要较长时间因而可能导致 UI 冻结的本地操 作;
(3) 区分各种优先级的任务; (4) 提高应用程序启动和初始化的性能。 进行多线程程序设计时应当注意:线程越多,占用内 存也越多,线程之间需要协调和管理,对共享资源的访问 会相互影响,太多的线程会导致控制复杂和系统不稳定(线 程之间的切换会耗费大量的CPU计算时间)。这些都是使用 多线程时的不利因素,因此应当慎重。
为了解决串行模型存在的问题,可以使用并发模型。 并发模型使用单个线程等待客户端请求,当请求到来时, 创建新线程来处理请求。等待客户请求的线程继续等待另 一个客户端请求,新线程完成请求处理。当新线程处理完 客户端请求后,随即退出。
5
由于并发模型为每个客户端都会创建一个新的线程,客户 端请求能够很快地被处理,并且每个客户端请求都有自己 的线程,因此服务效率要明显好于串行模型,且基于并发 模型的服务器程序具有良好的伸缩性,当升级硬件时,服 务器程序的性能可以得到提高。
下面以WinSock的面向连接服务器编程为例,说明并 发模型的工作原理(如图8-1所示)。
首先安排主线程作为监听线程(执行路径),创建一个 套接字监听客户端的连接请求。当有一个连接请求到达时, 让主线程创建一个新的套接字。
6
监听套接字将接受的客户端连接递交给新的套接字,然后 创建一个线程并由该线程提供具体的服务,而主线程继续 监听来自客户端的连接请求。线程服务结束后,释放资源。 当主线程再次收到下一个连接请求时(前面线程的服务不一 定结束),再创建一个新套接字接收连接请求,并创建相应 线程提供服务。依次类推,从而实现服务器的并行服务。 这样不但满足了少量服务器端为多个客户端服务的需求, 也为各个用户数据传输的独立性提供了保证,可以说是对 并发服务请求问题的初步解决(更深层次的问题讨论参见8.6 节)。
10
一个公司至少得有一个职员,同理,一个进程至少包含一 个线程(事实上目前几乎已经没有单线程的网络商业应用软 件),浏览器就是一个很好的多线程的例子。在浏览器中, 用户可以同时完成下载Java小应用程序或图像、滚动页面、 播放动画和声音、打印文件等,就是基于多线程技术实现 的。多线程的使用可以提高CPU的利用率,这是因为在多 线程程序中,当一个线程必须等待时,CPU可以运行其他 的线程而不是等待,从而大大提高了程序的效率。
12
8.3 线程基本操作函数
线程在操作系统中的存在有多种状态,好比人的生老 病死,相对应于初始态、可运行态、阻塞/非可运行态和死 亡态等四种状态。程序设计中,进入或改变这些状态需要 一些函数的支持,学会运用这些函数也就掌握了多线程的 编程技术。Windows为用户提供了完备的基本线程操作, 下面具体来看一下这些基本线程操作函数。