信息安全系统设计基础第十三周学习总结
第十二章 并发编程
并发
:逻辑控制流在时间上重叠
应用级并发
:
访问慢速设备
人机交互
通过推迟工作以降低延迟
服务多个客户端
在多核机器上进行并行计算
进程
:
进程并发服务器
:在父进程中接受客户端连接请求,再创建一个新的子进程来为每个新客户端提供服务。
进程共享文件表,但不共享用户地址空间。
基于I/O多路复用的并发编程
使用select函数,要求内核挂起进程,只有在一个或多个I/O事件发生后,才将控制返回给应用程序
两个输入:读集合
读集合的基数n
事件驱动程序
:流因为某种事件而前进
状态机
:状态,输入事件和转移
基于线程的并发编程
线程
:运行在进程上下文中的逻辑流
线程上下文
:线程ID,栈,栈指针,程序计数器,通用目的寄存器和条件码
运行在一个进程里的线程共享该进程的虚拟地址空间,包括代码,数据,堆,共享库和打开的文件
Posix线程
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
”);
return NULL;
}
pthread_create返回时,参数tid包含新创建线程的ID
pthread_join函数会阻塞,直到进程tid终止,将线程例程返回的(void*)指针赋值为thread_return指向的位置,然后回收已终止线程占用的所有存储器资源。
多线程程序的共享变量
一个变量是共享的,当且仅当多个线程引用这个变量的某个实例
寄存器从不共享,虚拟存储器总是共享的
同步线程
一般而言,你无法预测操作系统能否为你的线程选择一个正确的顺序
不安全区
:毗邻不安全区的状态并不是不安全区的一部分
信号量
信号量s是具有非负整数值得全局变量
信号量不变性:一个正确初始化了的信号量不可能有一个负值。
基于预线程化的并发服务器
服务器由一个主线程和一组工作者线程构成
主线程不断接受连接请求,并将得到的连接描述符放在一个有限的缓冲区中
每个工作者线程反复地从共享缓冲区中取出描述符,为客户端服务,然后等待下一个描述符
并行程序
:一个运行在多个处理器上的并发程序
并行程序往往写为每个核
上只运行一个线程
加速比:
强扩展
: Sp = T1 / Tp
Tk是k个核上的运行时间,p为处理器核的数量
绝对加速比
:T1为程序顺序执行版本的执行时间的Sp
相对加速比
:T1位程序并行版本在一个核上的执行时间的Sp
效率:Ep = Sp / p = T1 / (p*Tp)
线程安全
:当且仅当一个函数被多个并发线程反复调用时,他会一直产生正确结果
四类线程不安全函数:
1 不保护共享变量的函数
2 保持跨越多个调用的状态的函数
3 返回指向静态变量的指针的函数
4 调用线程不安全函数的函数
可重入性
:当函数被多个线程调用,不会引用任何共享数据
显式可重入
:所有函数参数都是传值传递,所有数据引用都是本地自动栈变量
隐式可重入
:显式可重入加上一些参数是引用传递(指向非共享数据的指针)
竞争
:当一个程序的正确性依赖于,一个线程要在另一个线程到达y点之前到达它的控制流中的x点,就会发生竞争
线程化的程序必须对任何可行的轨迹线都正确工作
死锁
:一组线程被阻塞了,等待一个永远也不会为真的条件。
死锁不总是可以预测的,而错误常常不可重复。
互斥锁加锁顺序规则
:如果对于程序中每对互斥锁(s,t),给所有的锁分配一个全序,每个线程按照这个顺序来请求锁,并且按照逆序来释放,那么它就是无死锁的。