线程安全
来源:互联网 发布:天佑鲍比知乎 编辑:程序博客网 时间:2024/06/09 15:52
假设一种情况,编写mysleep()函数。
#include <stdio.h>#include <unistd.h>#include <signal.h>void myhandler(int sig){ printf("%d signal\n", sig);}int mysleep(int timeout){ struct sigaction act, oact; act.sa_handler = myhandler; act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaction(SIGALRM, &act, &oact); alarm(timeout); pause(); int ret = alarm(0); sigaction(SIGALRM, &oact, NULL); return ret;}int main(){ while(1) { mysleep(2); printf("mysleep 2s\n"); }}
但如果在定时器刚设定好时,
系统却执行高优先级的进程去了,并且需要较长时间,
此时定时器已经设置,但是进程却没有被挂起,
此时定时器可能已经到达时间了,内核发送SIGALRM信号给该进程,但进程处于未决状态,
等到高优先级进程执行完毕,系统开始执行该进程的下一句pause(),
进程被挂起,一直在等待,此时已经没有定时器来唤醒进程,就会导致进程结果出现异常。
这是因为进程时序的问题而导致的进程结果出现异常,也被称为竟态条件。
那么如何解决这个问题呢?
1.屏蔽SIGALRM信号
2.alarm(n s)//设置定时器
3.解除屏蔽
4.pause()
但是在解除屏蔽和挂起信号之间,SIGALRM仍有可能递达,那么只要将解除屏蔽和递达一起执行就可以了,将它们合成一个原子操作,sigsuspend()包含了pause()的挂起等到功能。
#include <stdio.h>#include <unistd.h>#include <signal.h>void myhandler(int sig){ printf("%d signal\n", sig);}int mysleep(int timeout){ struct sigaction act, oact; sigset_t nmask, omask, smask; act.sa_handler = myhandler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGALRM, &act, &oact); sigemptyset(&nmask); sigaddset(&nmask, SIGALRM); sigprocmask(SIG_BLOCK, &nmask, &omask); alarm(timeout); smask = omask; sigdelset(&smask, SIGALRM); sigsuspend(&smask); int ret = alarm(0); sigaction(SIGALRM, &oact, NULL); sigprocmask(SIG_SETMASK, &omask, NULL); return ret;}int main(){ while(1) { mysleep(2); printf("mysleep 2s\n"); }}
阅读全文
0 0
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- java读取文件与写文件
- 自己写 bootloader
- 清空redis
- android开发艺术探索 学习笔记(三) IntentFilter的匹配规则
- 前嗅ForeSpider采集大众点评数据教程
- 线程安全
- adb查看手机设备型号、品牌、机型等信息
- java自定义注解
- js缓存变量,减少DOM操作开销
- java实现AES加密解密
- Apache Kafka0.10.0.0集群部署
- EXE和SYS通信(ReadFile WriteFile DO_BUFFERED_IO) 缓冲区方式
- Spring 在静态工具类中使用注解注入bean
- MYSQL数据库 的 decimal 字段类型