一、描述

在操作系统中,异步并发执行环境下的一组进程,因为相互制约关系,进而互相发送消息、互相合作、互相等待,使得各进程按一定的顺序和速度执行,称为进程间的同步。具有同步关系的一组并发进程,称为合作进程,合作进程间互相发送的信号,称为消息或事件。

这种需要进程间同步的情况,是可以想见的,例如几个进程访问“临界资源”。而为了解决进程间的同步问题,引入信号量的概念。

二、异步执行

  所谓异步执行命令,就是说一个线程用于接收解析命令,另外一个线程用于实际执行命令。实际工程中,经常会遇到有许多种命令要在一个线程中得到解析并执行,有些命令耗时短,可以在这个线程中完成;但是,有些命令耗时长,如果也放在这个线程中,则影响该线程接收(其他命令)。所以,此时可以考虑用异步执行的方案,将耗时短的命令,就放在接收解析线程中;而将耗时长的命令,则用异步执行的方案,将接收与实际执行分离,以避免接收线程受到严重阻塞。

example:

本例程中,用主线程创建了两个子线程pthread1和pthread2,其中线程pthread1用于产生命令(模仿接受解析过程),而线程pthread2用于实际执行命令。

代码如下:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<pthread.h>
  4 #include <semaphore.h>
  5
  6 /* 将信号量定义为全局变量,方便多个线程共享 */
  7 sem_t sem;
  8
  9 /* 线程1和线程2的公用命令 */
 10 int gCmd = 0;
 11
 12 /* 同步线程1和线程2的全局变量 */
 13 static int gIsExecFlag = 0;
 14
 15 /* 定义线程pthread1 */
 16 static void * pthread1(void *arg)
 17 {
 18     /* 线程pthread1开始运行 */
 19     printf("pthread1 start!\n");
 20
 21     while(1)
 22     {
 23         /* 等待没有命令正在执行 */
 24         while(gIsExecFlag);
 25
 26         /* 更新命令 */
 27         gCmd++;
 28         if(gCmd == 10)
 29         {
 30             /* 释放信号量 */
 31             sem_post(&sem);
 32
 33             /* 发送命令结束 */
 34             return NULL;
 35         }
 36
 37         /* 释放信号量 */
 38         sem_post(&sem);
 39
 40         /* 等待线程2执行命令 */
 41         sleep(1);
 42     }
 43 }
 44
 45 /* 定义线程pthread2 */
 46 static void * pthread2(void *arg)
 47 {
 48     int tmp;
 49
 50     /* 线程pthread2开始运行 */
 51     printf("pthread2 start!\n");
 52
 53     while(1)
 54     {
 55         if (sem_wait(&sem) != 0)
 56         {
 57             printf("Error!\n");
 58         }
 59
 60         /* 正在执行的标志置1 */
 61         gIsExecFlag = 1;
 62
 63         /* 线程2接受来自线程1的命令,并打印 */
 64         tmp = gCmd;
 65         printf("now execute the cmd,and the code of cmd is %d.\n", tmp);
 66
 67         /* 执行命令需要时间:3s,模仿实际命令执行 */
 68         sleep(3);
 69
 70         /* 正在执行的标志清0 */
 71         gIsExecFlag = 0;
 72
 73         if(gCmd == 10){
 74             /* 命令执行结束 */
 75             return NULL;
 76         }
 77     }
 78 }
 79
 80 /* main函数 */
 81 int main(int agrc,char* argv[])
 82 {
 83     pthread_t tidp1,tidp2;
 84
 85     /* 初始化信号量sem,注意初始值为0 */
 86     sem_init(&sem, 0, 0);
 87
 88     /* 创建线程pthread1 */
 89     if ((pthread_create(&tidp1, NULL, pthread1, NULL)) == -1)
 90     {
 91         printf("create error!\n");
 92         return 1;
 93     }
 94
 95     /* 同步,让线程1先执行 */
 96     usleep(10);
 97
 98     /* 创建线程pthread2 */
 99     if ((pthread_create(&tidp2, NULL, pthread2, NULL)) == -1)
100     {
101         printf("create error!\n");
102         return 1;
103     }
104
105     /* 等待线程pthread1释放 */
106     if (pthread_join(tidp1, NULL))
107     {
108         printf("thread is not exit...\n");
109         return -2;
110     }
111
112     /* 等待线程pthread2释放 */
113     if (pthread_join(tidp2, NULL))
114     {
115         printf("thread is not exit...\n");
116         return -2;
117     }
118
119     return 0;
120 }

代码重点解析:

进程pthread1和进程pthread2之间单纯用信号量sem同步,无法解决发送线程pthread1,在线程pthread2正在执行命令时,又写入了新的命令的问题,造成命令执行错乱。为了解决这个问题,引入全局变量gIsExecFlag用于同步。经过信号量sem和全局变量gIsExecFlag的完美配合,就可以实现命令发送与执行过程的有序配合。

测试效果

编译命令:

#arm-linux-gcc -o pthread pthread.c -lpthread

执行结果:

后续分析

由上图可知,两个线程的整体执行周期,并非是线程pthread1和线程pthread2周期的和,而是取两者中的最大者。实际上,这也很容易想见,两个线程的通信速度,取决于两个线程中速度最慢者,也对应这个结论。

经过测试,不论发送线程和执行线程的速度孰大孰小,总体的执行结果是一样的,都能保证命令执行流程的正确。所以,就可以证明上述代码的可行性。但是,需要注意的是,线程之间的同步时间还是有限制的,线程pthread1的睡眠时间应≥10ms,否则将会出现执行流程的错误。

参考资料:Linux线程的信号量同步

linux应用编程之进程间同步相关推荐

  1. Linux系统编程06 --进程间关系

    文章目录 六.进程间关系 终端 **tty** 网络终端 进程组 会话 setsid()创建新会话函数 getsid()获取会话sid函数 守护进程 守护进程创建步骤 六.进程间关系 终端 ​ 在UN ...

  2. Linux系统编程(四)--进程间关系

    文章目录 1 进程扇与进程链 2 进程组 2.1 概念 2.1 进程组的创建与设置 3 会话 3.1 概念 3.2 创建会话 4 控制终端.前台进程组与后台进程组 5 后台进程组与控制终端 6 孤儿进 ...

  3. linux 进程间读写锁,Linux系统编程—进程间同步

    我们知道,线程间同步有多种方式,比如:信号量.互斥量.读写锁,等等.那进程间如何实现同步呢?本文介绍两种方式:互斥量和文件锁. ##互斥量mutex 我们已经知道了互斥量可以用于在线程间同步,但实际上 ...

  4. 利用管道实现进程间同步

    进程间同步是指进程的运行有先后顺序,如A进程等待B进程执行完某个动作A进程才能继续往下运行.进程间通信的方法都可以用来同步,只是操作是否方便的一个问题.复习了UNIX高级编程,觉得POSIX的信号量是 ...

  5. android p获取通话记录_Android 底层的进程间同步机制

    作者:Android面试官 进程间通信的经典实现 进程间通信(Inter-process communication,IPC)指运行在不同进程中的若干线程间的数据交换,可发生在一台机器上,也可通过网络 ...

  6. (28)System Verilog进程间同步(事件event)

    (28)System Verilog进程间同步(事件event) 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog进程间同步(事件eve ...

  7. (30)System Verilog进程间同步(邮箱mailbox)

    (30)System Verilog进程间同步(邮箱mailbox) 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog进程间同步(邮箱m ...

  8. (29)System Verilog进程间同步(旗语semaphore)

    (29)System Verilog进程间同步(旗语semaphore) 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog进程间同步(旗 ...

  9. vbs结束进程代码_物联网学习教程—Linux系统编程之进程控制

    Linux系统编程之进程控制 一.结束进程 首先,我们回顾一下 C 语言中 continue, break, return 的作用: continue: 结束本次循环 break: 跳出整个循环,或跳 ...

最新文章

  1. C语言实现傅里叶变换函数dft,idft,fft,ifft
  2. 2.1.1 物理层的基本概念
  3. 配置Exchange 2007边缘同步
  4. vue 关闭弹如何销毁子组件_vue中的eventBus会产生内存泄漏吗
  5. 多目标跟踪(MOT)论文随笔-SIMPLE ONLINE AND REALTIME TRACKING (SORT)
  6. LA 3458——Bridge
  7. linux tee 重定向_快乐的linux命令行-重定向
  8. 电子邮件乱码的解决方法
  9. c语言程序设计卡特兰数问题,求解圆上2N个点的连线问题(卡特兰数)
  10. 台式计算机接口示意图,台式机硬盘接口_台式机硬盘接口图解
  11. 乔本生涯, 为什么要这样做
  12. 想成为年薪30W+的运营,你必须具备这4个“运营思维”
  13. 吴恩达Course1《神经网络与深度学习》week2:神经网络基础 测验及作业
  14. 生产注意事项(分片集群)
  15. (OpenCV+Python)--目标跟踪,卡尔曼滤波+鼠标轨迹跟踪
  16. 【系统集成项目管理工程师】项目立项
  17. android 防刷机
  18. Rosalind第68题:Counting Optimal Alignments
  19. i3 1215U 和 i5 1235U选哪个好
  20. FirstBlood

热门文章

  1. 决胜圣诞,女神心情不用猜!
  2. 如何高效运作机器学习团队(机器学习入门第四篇)
  3. [外挂1] MFC 鼠标位置设置
  4. mysql主从复制延迟问题的相关知识与解决方案
  5. Android开发的内存问题
  6. OSChina 周六乱弹 ——属于程序员的情话
  7. Comparator和Comparable (转)
  8. 12M电信宽带,为什么12台机器上网,总是掉线?有什么办法解决?请给位高手指教...
  9. 图像扩充边界_使用机器学习来索引数十亿图像中的文本
  10. 如何借助大数据提升医疗质量管理