《深入理解计算机系统》--并发编程
这也是一本很出名的书,在很早的时候读过一些,这次从后面开始读,看有没有新的体会。
如果逻辑流在时间上重叠,那么他们就是并发的,硬件异常处理程序、进程和UNIX信号处理程序都是熟悉的例子。并发现象不仅在内核中存在,在应用级别的程序中也存在。
访问慢速的I/O设备
与人交互
通过推迟工作以降低延迟
服务多个网络客户端
在多核机器上进行并行计算
进程
I/O多路复用
线程
其中后边三种是操作系统提供给应用程序的三种构造并发程序的方法。一、基于进程的并发编程
构造并发程序最简单的方法就是使用进程,使用fork()等一些列的函数。看一个使用进程并发的实例:
/* * badcnt.c - An improperly synchronized counter program *//* $begin badcnt */#include "csapp.h"#define NITERS 200000000void *count(void *arg);/* shared counter variable */unsigned int cnt = 0;int main() { pthread_t tid1, tid2; Pthread_create(&tid1, NULL, count, NULL); Pthread_create(&tid2, NULL, count, NULL); Pthread_join(tid1, NULL); Pthread_join(tid2, NULL); if (cnt != (unsigned)NITERS*2)printf("BOOM! cnt=%d\n", cnt); elseprintf("OK cnt=%d\n", cnt); exit(0);}/* thread routine */void *count(void *arg) { int i; for (i = 0; i < NITERS; i++)cnt++; return NULL;}/* $end badcnt */
这个错误会引发操作系统中很多很重要的问题:互斥、PV操作等等。
可以参考这个
无论哪种并发机制,同步对共享数据的并发访问都是一个困难的问题。提出对信号量的P和V操作就是为了帮助解决这个问题。信号量操作可以用来提供对共享数据的互斥访问,也对诸如生产者-消费者程序中有限缓冲区和读者-写者系统中的共享对象这样的资源访问进行调度。
书中还有一段话值得回味,信号量提供了一种很方便的方法来确保对共享变量的互斥访问。基本思想是将每个共享变量(或者一组相关的共享变量)与一个信号量s(初始为1)联系起来,然后用P(s)和V(s)操作将相应的临界区包围起来。以这种方式来保护共享变量的信号量叫做二元信号量。因为它的值总是0或者1.以提供互斥为目的的二元信号量常常也称为互斥锁。
除了提供互斥之外,信号量的另一个重要作用是调度对共享资源的访问。在这种场景下,一个线程用信号量操作来通知另一个线程,程序状态中的某个条件已经为真了。两个经典而有用的例子是生产者-消费者和读者-写者问题。
PS:在开头想引用孔夫子的话:学而不思则罔,思而不学则殆!!觉得这句话对于CSer再合适不过,大概宽泛的想一下,计算机的技术太多太多,从上层应用下层开发,不管是那一块学精通都可以混一辈子饭吃!!但是总想什么都会还是不现实的,所以还是跟着自己的兴趣来,还有就是对一些东西必须去思考去理解!!!思考理解!!!!