第十二章 并发编程
2015-12-06 00:07
211 查看
第十二章 并发编程
概述:如果逻辑控制流在时间上重叠,那么他们就是并发的
应用级并发在其他情况下的应用
访问慢速I/O设备与人交互
通过推迟工作以降低延迟
服务多个网络客户端
在多核机器上进行并发计算
12.1基于进程的并发编程
构造并发程序最简单的方法就是用进程
常用函数
forkexec
waitpid
原理
在父进程中接受客户端连接请求,然后创建一个新的子进程来为每个新客户端提供服务。12.1.1基于进程的并发服务器
关于服务器需要说明的地方、
要包括一个sigchld处理程序,来回收僵死程序父子进程必须关闭他们各自的connfd
直到父子进程的connfd都关闭了,到客户端的链接才会终止
12.1.2关于进程的优劣
1.优点:防止虚拟存储器被错误覆盖2.缺点:开销高,共享状态信息才需要IPC机制
12.2基于I/O多路复用的并发编程
使用I/O多路复用的并发编程的原因
同时响应下面两个请求网络客户端发起连接请求
用户在键盘上输入命令行
原理
就是使用select函数要求内核挂起进程,只有在一个或多个I/O事件发生后,才将控制返回给应用程序。12.2.1基于I/O多路复用的并发事件驱动服务器
事件驱动程序:将逻辑流模型化为状态机。状态机:
状态
输入事件
转移
12.2.2 I/O多路复用技术的优劣
1.优点相较基于进程的设计,给了程序员更多的对程序程序的控制
运行在单一进程上下文中,所以每个逻辑流都可以访问该进程的全部地址空间,共享数据容易实现
可以使用GDB调试
高效
2.缺点
编码复杂
不能充分利用多核处理器
12.3基于线程的并发编程
是以上两种方法的混合
线程有内核自动调度多个线程运行在单一进程的上下文中
12.3.2posix线程
void *thread(void *vargp); int main() { pthread_t tid; Pthread_create(&tid, NULL, thread, NULL); Pthread_join(tid,NULL); exit(0); } void *thread(void *vargp) { printf(“Hello , world\n”); return NULL; }
12.3.3创建线程
线程通过调用pthread_create函数来创建其它线程#include <pthread.h> typedef void *(func)(void *); int pthread_create(pthread_t *tid, pthread_attr_t *attr, func *f, void *arg);
12.3.4终止线程
顶层的线程例程返回调用pthread_exit函数
如果主线程调用,会先等待所有其他对等线程终止,再终止主线程和整个进程,返回值为pthread_return
某个对等线程调用Unix的exit函数,会终止进程与其相关线程
另一个对等线程通过以当前线程ID作为参数调用pthread_cancle来终止当前线程
12.4多线程程序中的共享变量
一个变量是共享的,当且仅当多个线程引用这个变量的某个实例。
12.5用信号量同步线程
第一个 CreateSemaphore函数功能:创建信号量
函数原型:
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName
);
函数说明:
第一个参数表示安全控制,一般直接传入NULL。
第二个参数表示初始资源数量。
第三个参数表示最大并发数量。
第四个参数表示信号量的名称,传入NULL表示匿名信号量。
第二个 OpenSemaphore
函数功能:打开信号量
函数原型:
HANDLE OpenSemaphore(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
函数说明:
第一个参数表示访问权限,对一般传入SEMAPHORE_ALL_ACCESS。详细解释可以查看MSDN文档。
第二个参数表示信号量句柄继承性,一般传入TRUE即可。
第三个参数表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个信号量。
第三个 ReleaseSemaphore
函数功能:递增信号量的当前资源计数
函数原型:
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
函数说明:
第一个参数是信号量的句柄。
第二个参数表示增加个数,必须大于0且不超过最大资源数量。
第三个参数可以用来传出先前的资源计数,设为NULL表示不需要传出。
由于信号量是内核对象,因此使用CloseHandle()就可以完成清理与销毁了。
12.6使用线程提高并行性
四类线程不安全函数:
不保护共享变量的函数保持跨越多个调用的状态的函数
返回指向静态变量的指针的函数
调用线程不安全函数的函数
可重入性:当函数被多个线程调用,不会引用任何共享数据
显式可重入:所有函数参数都是传值传递,所有数据引用都是本地自动栈变量
隐式可重入:显式可重入加上一些参数是引用传递(指向非共享数据的指针)
竞争:当一个程序的正确性依赖于,一个线程要在另一个线程到达y点之前到达它的控制流中的x点,就会发生竞争
线程化的程序必须对任何可行的轨迹线都正确工作
死锁:一组线程被阻塞了,等待一个永远也不会为真的条件。
死锁不总是可以预测的,而错误常常不可重复。学习心得
这周的内容和操作系统的内容有相似的地方,都是从分析并发执行的程序的状况。操作系统对于进程的调用,进程的死锁情况的解决以及更多别的问题讲的更详细。但是本书更注重从代码的角度讲述并发编程的问题,所以通过
学习这门课,使我从不同的角度了解了操作系统。
参考文献:
深入理解计算机系统第十二章
20135202闫佳歆同学的博客
zhanghaodx082的专栏http://blog.csdn.net/zhanghaodx082/article/details/11932865
相关文章推荐
- php+mysql的utf-8中文乱码问题的解决方法
- The road from my heart to java chapter4
- Ubuntu 14.04 安装 phpstrom 10
- JavaEE: JSP与Servlet
- Java并发编程资料整理,持续更新
- eclipse导出web项目而引起获取class路径不是期待值!
- spring Bean实例生命周期行为
- 理解CacheLine与写出更好的JAVA
- 2分钟学会sonar安装使用
- java实现线性顺序表
- java实现线性单链表
- PyQt5教程(五)——对话框
- 搭建 vsftpd FTP服务器
- vsftpd详细配置命令
- java中toString()方法
- java学习第五天
- java学习第六天
- java中 this 和 super的区别
- 项目开发之代码优化
- 强制关闭myeclipse出现的问题