85-线程同步
来源:互联网 发布:大数据开发需要学什么 编辑:程序博客网 时间:2024/06/05 11:33
本文通过一个具体案例来说明什么是线程同步。
1. 问题提出
学生线程写作业,老师线程检查作业。要求:只有学生线程写完作业了,老师线程才能检查作业。
在此问题中,有两个线程:学生线程和老师线程,和以往的线程互斥不一样的是,线程互斥之间没有明确的的执行顺序上的要求。而线程同步,有了顺序上的要求,即有先后关系:只有学生线程完成了作业以后,老师线程才能够去运行!
2. 解决思路
在我们没有学习线程同步的方法前,除了采用信号量机制和轮询,好像还没有更好的方法来解决此问题。如果不允许使用信号量的话,用轮询该怎么做?轮询是指:老师线程可以不断的去询问学生作业到底有没有完成作业。
具体做法是采用全局变量 finished 做标记,初始化为 0,表示学生还未完成作业。学生如果完成了作业,会将 finished 变量设置为 1.
另一方面,老师线程不断的检查 finished 变量是否为 1 来判断学生完成了作业。
下面是伪代码:
void student() { // doing homework sleep(5); lock(mutex); finished = 1; unlock(mutex);}void teacher() { // 不断检查标记是否为 1 lock(mutex); while(finished == 0) { unlock(mutex); sleep(1); lock(mutex); } unlock(mutex); // 执行到这里说明学生已经完成了作业}
很显然,全局变量 finished 属于共享资源,需要使用互斥手段对其进行互斥访问,否则容易出现错误。
说明:在此例中不需要给 finished 变量加互斥锁也不会错,因为老师线程只做了读操作。但是,为了防止产生竞争错误,其次为了后续讨论方便,这里索性加上互斥锁。
3. 程序清单
3.1 代码
#include <stdio.h>#include <pthread.h>int finished = 0;pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;void* do_homework(void* arg) { // doing homework sleep(5); // finished pthread_mutex_lock(&lock); finished = 1; pthread_mutex_unlock(&lock);}void* check_homework(void* arg) { // 打电话 sleep(1); // 电话接通 pthread_mutex_lock(&lock); // 作业写完了吗? printf("老师:作业写完了吗?!\n"); while(finished == 0) { // 没写完呐! printf("学生:没写完呐!\n"); pthread_mutex_unlock(&lock); // 好的,你接着写 printf("老师:好的,你接着写吧!\n"); printf("-------------------------\n"); sleep(1); pthread_mutex_lock(&lock); printf("老师:作业写完了吗?!\n"); } printf("学生:写完啦!\n"); pthread_mutex_unlock(&lock); printf("老师开始检查---------------\n");}int main() { pthread_t tid1, tid2; pthread_create(&tid1, NULL, do_homework, NULL); pthread_create(&tid2, NULL, check_homework, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); return 0;}
3.2 编译和运行
- 编译和运行
$ gcc do_homework.c -o do_homework -lpthread$ ./do_homework
- 运行结果
图1 运行结果
3.3 结果分析
从图 1 中可以看到,老师一直问了学生 5 次,其中 4 次询问得到的答复都是没写完……
虽然本程序的结果正确,但是大家也可以看到,老师反复的询问学生,效率低下。如果学生做作业十分的慢,也不知道要做多久,老师就会一直问下去,这无疑是对老师宝贵时间的浪费(也就是浪费 cpu 资源)。
如果有一种方法,可以让学生在完成后作业后唤醒老师线程,不就好了吗?这就是所谓的好莱坞式编程:Do not call me! I will call you (别打我电话,我会通知你的).
在下一节里就会介绍这种技术——条件变量。
4. 总结
- 理解何为线程同步
- 知道在没有信号量和条件变量的时候,如何使用互斥来完成线程同步
练习:理解轮询机制是如何工作的,同时完成本文中的实验。
- 85-线程同步
- 线程同步--线程同步--线程同步--线程同步--线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 线程同步
- 百度地图api获取可视区方法
- 计算某日期与当前日期天数
- 这是第一篇博客
- SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
- HDU 1695 GCD【欧拉函数+容斥原理】
- 85-线程同步
- certificate verify fails (https://gems.ruby-china.org错误
- [HDU3076]ssworld VS DDD(概率dp)
- ios swift WKWebView (一)基本了解
- 进程创建时sched_fork
- html5 canvas 详细使用教程
- 【转】CUDA-GPU架构
- 微信开放平台和公众平台的区别?
- Pandas数据预处理与透视表