c++网络编程学习笔记(5)

 
CHAPTER 4. 操作系统并发机制概述
一、同步事件多路分离
“同步事件多路分离器”是OS提供的一个函数,用于在一组事件源上等待特定事件的发生。当一个或多个事件源被激活时,函数将返回至调用者。于是,调用者可以处理这些“来自多个源”的事件。通常,同步事件多路分离器被用作“反应式服务器”事件循环的基本构件。
大都数操作系统都支持一个或多个“同步事件多路分离”函数,例如:
l       poll()函数,来自 System V UNIX;
l       WaitForMultipleObjects()函数,由Win32提供;
l       Select()函数,在I/O句柄上对事件源进行多路分离。
Select()函数的C API版本:
Int select ( int width,
         Fd_set* read_fds,
               Fd_set* write_fds,
         Fd_set* except_fds,
               Struct timeval* timeout );
Fd_set是一个结构,表示一组句柄(一个句柄集),用于检查I/O事件。Select()函数通过修改它的fd_set参数,向调用者通知“活动”和“非活动”句柄的情况。
 
二、多进程机制
不同的操作系统提供的“进程控制”功能大不相同。但是,在多进程操作系统中,以下几方面的功能是共有的。
l       进程生存期操作
创建: fork()和exec() (POSIX)
           CreateProcess()   (Win32)
终止:
     ·自愿终止:ExitProcess()     (Win32)
                              Exit()    (POSIX)
·无意终止:TerminateProcess()     (Win32)
l       进程同步操作
当进程退出时,大多数操作系统都会保留这个进程的标识信息和退出状态。这样,父进程可以与之同步,并获得它的退出状态。
常见的进程同步函数有:
·POSIX的wait()和waitpid()函数
·Win32的WaitForSingleObject()和WaitForMultipleObjects()函数
l       进程属性操作
大多数操作系统会提供一些函数,用来获取和设置进程的各种属性。
 
三、多线程机制
线程是进程中的执行单元。
操作系统提供处理线程的机制:
l       线程生存期操作
· 程序的主线程在一个进程开始执行时隐含创建。其他线程都通过显式调用“线程创建”函数创建: CreateThread()     (Win32)
· 终止
       自愿终止: ExitThread()     (Win32)
         无意终止: TerminateThread()     (Win32)
l       线程同步操作
很多OS线程机制允许创建以下两种线程:
· 分离式 —— 当“分离式”线程退出时,OS会自动回收这个线程的“状态”和“退出状态”使用过的空间。
· 连接式 —— 当“连接式”线程退出时,OS会保留它的“标识信息”和“退出状态”,这样,另一个线程可以与之同步,并得到它的“退出状态”。
线程同步机制的常见例子有:
Win32的WaitForSingleObject()和WaitForMultipleObjects()函数。
一些OS平台提供了同步函数,允许线程之间执行挂起和恢复操作。一些平台允许线程向同一进程中的其他线程发送信号。但是,这些操作一般不具可移植性,并且难以正确使用。
l       线程属性操作
大多数操作系统会提供一些函数,用来获取和设置线程的各种属性。
Win32中,线程的优先级查看和修改可以使用GetThreadPriority()和
SetThreadPriority()函数
l       线程专有存储空间 (TSS)
 
四、同步机制
常用的OS同步机制有:互斥体(mutex)、“多读取者/单写入者”锁 (readers/writer locks)、
信号量 (semaphores) 和条件变量 (condition variable)
 
1.       互斥体 (mutex)
当共享资源被多个线程并发访问时,为了确保这些资源的完整性,我们可以使用互斥体锁。互斥体可用来串行执行多个线程,这需要在代码中确定 关键段(critical section)——即,一次只能由一个线程执行的代码。
如果一个线程拥有互斥体,那么,它还得负责释放这个互斥体。
常见的互斥体有两种:
l       非递归互斥体 —— 如果当前拥有互斥体的线程在没有首先释放它的情况下,试图再次获得它,就会导致死锁或失败。
l       递归互斥体 —— 拥有互斥体的线程可以多次获得它而不会产生自死锁,只要这个线程最终以相同次数释放这个互斥体即可。
 
2 Readers/Writer
       可以通过以下方式之一访问共享资源:
l       多个线程并发读取资源,但不修改它。
l       一次只有一个线程修改资源,此时其他线程都不能对其进行读/写访问。
与互斥体不同的是,多个线程可以同时获得一个”readers/writer锁”执行读操作。
 
       3 .信号量锁
        从概念上说,信号量是可以原子递增和递减的非负整数。如果一个线程试图递减一个信号量,但这个信号量的值已经为0,则线程将会阻塞;另一个线程“发出(post)”这个信号,使信号量的值大于0之后,被阻塞的线程才会被释放。
          信号量维护状态信息,对信号计数值和被阻塞线程的数量进行记录。它们一般是通过“休止锁”来实现的;休止锁用来触发环境切换,以允许其他线程执行。和互斥体不同的是,释放信号量的线程不必是最初获得这个信号量的线程。
 
       4.条件变量
       和“互斥体”、“readers/writer锁”、“信号量”不同,条件变量提供了不同风格的同步方式。在前三种机制中,当“占有锁的线程”在关键段中执行代码时,其他线程会等待。与此相反,使用条件变量,线程可以调整和调度自己的处理过程。
 
 
副栏:同步机制的性能评估
l       和互斥体相比,条件变量和信号量的开销往往更大,因为它们的实现更为复杂。但是,和那些用户创建的东西相比,原始OS机制总是表现得更出色,因为后者可以利用“OS的内部特性”和“专门针对硬件的优化”。
l       和“readers/writer锁”相比,互斥体的开销通常更低,因为它们不需要管理多个“等待者集”。但是,多个“读取者”线程可以并行执行;所以,在多处理器上,如果将“readers/writer锁”用于访问那些“读操作”比“写操作”多的数据,“readers/writer锁”的伸缩性会表现得更好。
l       和递归互斥体相比,非递归互斥体效率更高。此外,如果程序员忘记释放递归互斥体,就会造成不易察觉的编程错误;但如果忘记释放的是非递归互斥体,则系统会立即通过“死锁”来暴露这些问题。
 
五、原始OS并发机制的局限性
通过以上原始OS并发机制来开发网络应用程序,会造成“可移植性”和“可靠性”方面的问题。后面讲的ACE“OS同步机制”类可以更好的解决这些问题。
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值