实验九 线程

1.线程的创建

编写程序模拟 Allen 和 Luffy 爬楼,楼层是从 1-10 层。 Allen 每上一层休息 10ms , Luffy 每上
一层休息 5ms . (需要注意的是 Allen 和 Luffy 是一起爬楼的,而非某个人先爬楼,爬完后接着另一
个人爬楼。)

因为线程用到 pthread 库,它不是 Linux 系统默认的库,所以在编译的时候要加上相应的参数

如果我们还是像以前一样用系统自带的 make 去编译,那么需要在当前文件夹下面创建一个 Makefile文件

添加以下内容:

之后我们就可以像之前一样用 make 命令来帮助我们编译。


如果把38行代码 sleep(3); 注释掉,重新编译运行,我们会发现结果和上面的差别很大。请大家思考为
什么会出现这样的结果?

这里看到线程根本没有运行。
2. 线程终止
sleep(3);
// 打印线程 id 号
printf("Allen id: %lx\n", allen);
printf("Luffy id: %lx\n", luffy);
return 0;
}
38
39
40
41
42
43
44
45线程的终止包括两大类,主动终止和被动终止。
主动终止
线程过程函数执行 return 正常返回,返回值是线程的退出码
线种过程函数执行 pthread_exit 函数退出,其参数是线程退出码
被动终止
在其它线程中调用 pthread_cancel 函数
任意线程调用 exit 、 _Exit 或者 _exit 导致整个进程终止
man 3 pthread_exit

man 3 pthread_cancel

例题:线程主动退出


例题:被动终止


例题:程序员 allen 和 luffy 两人去抢火车票,很不幸的是,只剩下 3 张票了。现在请你起两个线
程,去模拟抢票的过程。
抢票过程:
先查余票,如果有余票,下单
将余票数量减 1
有多少票抢多少票



上面的运行结果不是我们所期望的。你知道,系统中的余票只有 3 张。可是结果却显示 allen 和
luffy 各买了 3 张票!!!
互斥量
在 pthread 中,互斥量是用 pthread_mutex_t 数据类型表示的,通常它是一个结构体。在使用它前,
必须先对它进行初始化。有两种方法可以对它进行初始化:
通过静态分配的方法,将它设置为常量 PTHREAD_MUTEX_INITIALIZER
使用函数 pthread_mutex_init 进行初始化,如果是用此种方法初始化的互斥量,用完后还需要使用
pthread_mutex_destroy 对其进行回收。
互斥量的加锁和解锁



3 张票是被正常的抢走了,没有产生多抢的现象。 allen 还是比较厉害一点,抢了 2 张票,而 luffy
只抢到了一张票.
例题:学生线程写作业,老师线程检查作业。要求:只有学生线程写完作业了,老师线程才能检查作
业。
有两个线程:学生线程和老师线程,和以往的线程互斥不一样的是,线程互斥之间没有明确的的执行顺
序上的要求。而线程同步,有了顺序上的要求,即有先后关系:只有学生线程完成了作业以后,老师线
程才能够去运行!
在我们没有学习线程同步的方法前,除了采用信号量机制和轮询,好像还没有更好的方法来解决此问
题。如果不允许使用信号量的话,用轮询该怎么做?轮询是指:老师线程可以不断的去询问学生作业到
底有没有完成作业。


老师一直问了学生 5 次,其中 4 次询问得到的答复都是没写完……
虽然本程序的结果正确,但是大家也可以看到,老师反复的询问学生,效率低下。如果学生做作业十分
的慢,也不知道要做多久,老师就会一直问下去,这无疑是对老师宝贵时间的浪费(也就是浪费 cpu 资
源)。
如果有一种方法,可以让学生在完成后作业后唤醒老师线程,不就好了吗?
条件变量 condition
条件变量的数据类型是 pthread_cond_t.
初始化
通过常量 PTHREAD_COND_INITIALIZER 对其进行静态初始化
通过下面的函数进行初始化和回收:


posted @ 2021-06-14 20:17  taoshuai  阅读(9)  评论(0编辑  收藏  举报