信息安全系统设计第十三周学习总结
第十二章 并发编程#
基于进程的并发编程
构造并发程序最简单的方法就是用进程。如 fork()、exec()、waitpid。
基于进程的并发服务器
- 首先,用一个包括SIGCHLD处理程序,来回收僵死子进程的资源。
- 父子进程必须关闭他们各自的connfd拷贝。
- 直到父子进程的connfd都关闭,客户端的连接才会终止。
进程的优劣
父子进程间共享信息,(共享文件表),但不共享地址空间。进程有独立的地址空间既是优点也是缺点。此外,独立的地址空间使得进程共享状态信息变得困难。
基于I/O多路复用的并发编程
基于I/O多路复用的并发事件驱动服务器
状态机: 状态、输入事件、转移
I/O多路复用技术的优劣
优点:
1. 比基于进程的设计给了程序员更对的对程序行为的控制
2. 每个逻辑流都能访问该进程的全部地址空间
缺点:
1. 编码复杂
2. 不能充分利用多核处理器
基于线程的并发编程
线程 就是运行在上下文中的逻辑流。每个线程都有自己的线程上下文。
线程执行模型
主线程、对等线程
池、对等池
Posix线程
Posix线程是在C程序中处理线程的一个标准接口。
创建线程
#includu <pthread.h>
typedef void * (func)(void *);
int pthread_create(pthread_t *tid, pthread_attr_r *attr, func *f,void *arg);
返回:若成功则返回0,若出错则为非零。
#include <pthread.h>
pthread_t pthread_self(void);
返回:返回调用者的线程ID
终止进程
#include <pthread.h>
void pthread_exit(void *thread_return);
返回:若成功则返回0,若出错则为非零。
回收已终止线程的资源
#include <pthread.h>
int pthread_join(pthread_t tid,void **thread_return);
返回:若成功则返回0,若出错则为非零。
分离线程
#include <pthread.h>
int pthread_join(pthread_t tid,void **thread_return);
返回:若成功则返回0,若出错则为非零。
初始化线程
#include <pthread.h>
pthread_once_t once_control = PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *once_control,void (*init_routine)(void));
总是返回0.
一个基于线程的并发服务器
多线程程序中的共享变量
多线程程序的共享变量
线程存储器模型
将变量映射到存储器
- 全局变量
- 本地自动变量
- 本地静态变量
共享变量
用信号量同步线程
进度图
- 转换
- 不安全区
信号量
P V
使用信号量来实现互斥
二元信号量
互斥锁
加锁
解锁
计数信号量
禁止区
利用信号量来调度共享资源
- 生产者-消费者问题
- 读者-写者问题
使用线程提高并行性
其他并发问题
线程安全:
四个不安全函数类:
- 不保护共享变量的函数
- 保持跨越多个调用的状态的函数
- 返回指向静态变量的指针的函数
- 调用线程不安全函数的函数
可重入性:
- 显示可重入的
- 隐式可重入的
竞争
死锁
死锁状态、死锁区域
避免死锁的规则:
如果对于程序中每对互斥锁(s,t),给所有的锁分配一个全序,每个线程按照这个顺序来请求锁,并且按照逆序来释放,那么这个程序就是无死锁的。
参考资料: 《深入理解计算机系统》
问题:这周内容较多,目前12.4之后的内容都还来不及细看。下周继续看完。