linux应用编程之进程间同步
一、描述
在操作系统中,异步并发执行环境下的一组进程,因为相互制约关系,进而互相发送消息、互相合作、互相等待,使得各进程按一定的顺序和速度执行,称为进程间的同步。具有同步关系的一组并发进程,称为合作进程,合作进程间互相发送的信号,称为消息或事件。
这种需要进程间同步的情况,是可以想见的,例如几个进程访问“临界资源”。而为了解决进程间的同步问题,引入信号量的概念。
二、异步执行
所谓异步执行命令,就是说一个线程用于接收解析命令,另外一个线程用于实际执行命令。实际工程中,经常会遇到有许多种命令要在一个线程中得到解析并执行,有些命令耗时短,可以在这个线程中完成;但是,有些命令耗时长,如果也放在这个线程中,则影响该线程接收(其他命令)。所以,此时可以考虑用异步执行的方案,将耗时短的命令,就放在接收解析线程中;而将耗时长的命令,则用异步执行的方案,将接收与实际执行分离,以避免接收线程受到严重阻塞。
example:
本例程中,用主线程创建了两个子线程pthread1和pthread2,其中线程pthread1用于产生命令(模仿接受解析过程),而线程pthread2用于实际执行命令。
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include <semaphore.h> /* 将信号量定义为全局变量,方便多个线程共享 */
sem_t sem; /* 线程1和线程2的公用命令 */
int gCmd = ; /* 同步线程1和线程2的全局变量 */
static int gIsExecFlag = ; /* 定义线程pthread1 */
static void * pthread1(void *arg)
{
/* 线程pthread1开始运行 */
printf("pthread1 start!\n"); while()
{
/* 等待没有命令正在执行 */
while(gIsExecFlag); /* 更新命令 */
gCmd++;
if(gCmd == )
{
/* 释放信号量 */
sem_post(&sem); /* 发送命令结束 */
return NULL;
} /* 释放信号量 */
sem_post(&sem); /* 等待线程2执行命令 */
sleep();
}
} /* 定义线程pthread2 */
static void * pthread2(void *arg)
{
int tmp; /* 线程pthread2开始运行 */
printf("pthread2 start!\n"); while()
{
if (sem_wait(&sem) != )
{
printf("Error!\n");
} /* 正在执行的标志置1 */
gIsExecFlag = ; /* 线程2接受来自线程1的命令,并打印 */
tmp = gCmd;
printf("now execute the cmd,and the code of cmd is %d.\n", tmp); /* 执行命令需要时间:3s,模仿实际命令执行 */
sleep(); /* 正在执行的标志清0 */
gIsExecFlag = ; if(gCmd == ){
/* 命令执行结束 */
return NULL;
}
}
} /* main函数 */
int main(int agrc,char* argv[])
{
pthread_t tidp1,tidp2; /* 初始化信号量sem,注意初始值为0 */
sem_init(&sem, , ); /* 创建线程pthread1 */
if ((pthread_create(&tidp1, NULL, pthread1, NULL)) == -)
{
printf("create error!\n");
return ;
} /* 同步,让线程1先执行 */
usleep(); /* 创建线程pthread2 */
if ((pthread_create(&tidp2, NULL, pthread2, NULL)) == -)
{
printf("create error!\n");
return ;
} /* 等待线程pthread1释放 */
if (pthread_join(tidp1, NULL))
{
printf("thread is not exit...\n");
return -;
} /* 等待线程pthread2释放 */
if (pthread_join(tidp2, NULL))
{
printf("thread is not exit...\n");
return -;
} return ;
}
代码重点解析:
进程pthread1和进程pthread2之间单纯用信号量sem同步,无法解决发送线程pthread1,在线程pthread2正在执行命令时,又写入了新的命令的问题,造成命令执行错乱。为了解决这个问题,引入全局变量gIsExecFlag用于同步。经过信号量sem和全局变量gIsExecFlag的完美配合,就可以实现命令发送与执行过程的有序配合。
测试效果
编译命令:
#arm-linux-gcc -o pthread pthread.c -lpthread
执行结果:

后续分析

由上图可知,两个线程的整体执行周期,并非是线程pthread1和线程pthread2周期的和,而是取两者中的最大者。实际上,这也很容易想见,两个线程的通信速度,取决于两个线程中速度最慢者,也对应这个结论。
经过测试,不论发送线程和执行线程的速度孰大孰小,总体的执行结果是一样的,都能保证命令执行流程的正确。所以,就可以证明上述代码的可行性。但是,需要注意的是,线程之间的同步时间还是有限制的,线程pthread1的睡眠时间应≥10ms,否则将会出现执行流程的错误。
参考资料:Linux线程的信号量同步
linux应用编程之进程间同步的更多相关文章
- Linux系统编程—进程间同步
我们知道,线程间同步有多种方式,比如:信号量.互斥量.读写锁,等等.那进程间如何实现同步呢?本文介绍两种方式:互斥量和文件锁. 互斥量mutex 我们已经知道了互斥量可以用于在线程间同步,但实际上,互 ...
- linux信号量之进程间同步
概念 linux信号量: 允许多个线程同时进入临界区,可以用于进程间的同步. 和互斥锁(mutex)的区别: 互斥锁只允许一个线程进入临界区. 所在头文件: semaphore.h 主要函数 初始化函 ...
- 使用 Mutex 实现进程间同步
我们知道 Mutex 互斥量是可以用在线程间同步的,线程之间共享进程的数据,mutex 就可以直接引用.而进程有自己独立的内存空间,要怎样将它应用在进程间同步呢?为了达到这一目的,可以在 pthrea ...
- Python 多进程编程之 进程间的通信(在Pool中Queue)
Python 多进程编程之 进程间的通信(在Pool中Queue) 1,在进程池中进程间的通信,原理与普通进程之间一样,只是引用的方法不同,python对进程池通信有专用的方法 在Manager()中 ...
- Python 多进程编程之 进程间的通信(Queue)
Python 多进程编程之 进程间的通信(Queue) 1,进程间通信Process有时是需要通信的,操作系统提供了很多机制来实现进程之间的通信,而Queue就是其中的一个方法----这是操作系统开辟 ...
- 一个进程间同步和通讯的 C# 框架
转自原文 一个进程间同步和通讯的 C# 框架 threadmsg_demo.zip ~ 41KB 下载 threadmsg_src.zip ~ 65KB 下载 0.背景简介 微软在 .NE ...
- 一起talk C栗子吧(第一百回:C语言实例--使用信号量进行进程间同步与相互排斥一)
各位看官们.大家好,上一回中咱们说的是进程间同步与相互排斥的样例,这一回咱们说的样例是:使用信号量进行进程间同步与相互排斥. 闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,信号量是由著名 ...
- NET多线程之进程间同步锁Mutex
Mutex类似于lock.Monitor,都是为了解决多线程环境下,资源竞争导致的访问顺序问题.常见资源竞争有以下情况: 1.单例,如何确保单例: 2.IO文件操作,如果同时又多个线程访问同一个文件会 ...
- python并发——进程间同步和通信
一.进程间同步 对于一些临界资源,不能使用并发无限消耗,就需要设置专门的临界标示,比如锁或者信号量等 from multiprocessing import Process, Lock import ...
随机推荐
- Git服务器配置及本地克隆提交、服务器获取
1.服务器Git安装配置 相关链接 相关链接 注意ssh-keygen .修改权限 权限: 相关链接 2.本地获取 git clone name@ip:服务器项目位置 相关链接 3.创建 ...
- vue路由的配置
一.准备工作 1安装vue-cli npm install vue-cli -g 2检查是否安装成功 vue -V(大写V) 3初始化一个新的项目 vue init webpack vue-dem ...
- unicode编码和utf8编码的区别
编码格式不同在数据的传输和显示会有很大的影响.最近在使用的过程中发现一些网络文件 传输的编码格式问题,会影响文件的正常传输,于是查看了一下网上的资料,自己也写一篇 小总结. uicode是万国码,用1 ...
- python 定时修改数据库
当需要定时修改数据库时,一般我们都选择起一个定时进程去改库.如果将这种定时任务写入业务中,写成一个接口呢,定时进程显得有些不太合适?如果需要定时修改100次数据库,常规做法会启动100个进程,虽然这种 ...
- 【redis专题(2)】命令语法介绍之string
REDIS有5大数据结构:string,link,sortedset,sets,hash. 这5个结构我将用5篇文章来记录各自是怎么用的,然后再用一篇文章来说一下各自的应用场景: 更多语法请参考: h ...
- [20171205]uniq命令的输入输出.txt
[20171205]uniq命令的输入输出.txt --//前几天遇到XXD与通配符问题,链接http://blog.itpub.net/267265/viewspace-2147702/--//今天 ...
- windows10 VM12 安装Mac OS X 10.11
转载自:http://blog.csdn.net/j755ing/article/details/69400439 第一步: 下载 材料/工具: 下载 VMware Workstation 12 Pr ...
- ubuntu通过apt-get安装JDK8
安装python-software-properties apt-get install python-software-properties apt-get install software-pro ...
- Unity Chan 2D Asset
Unity Chan 2D Asset 4月份時,UNITY CHAN 官方網站推出了3D大島こはく,之後也有更新1.11版,而在六月12日時,則釋出了2D版本素材,一樣可以在UNITY CHAN 官 ...
- Linux之shell脚本for、while、case语句的高级用法
1.case语句的用法: [root@ELK-chaofeng test]# cat test3.sh #!/bin/bash while true ;do read -p "please ...