c - 信号量中的 P(&sem) 和 V(&sem) 如何影响代码?
问题描述
我有这个以函数“doit”作为参数之一执行 pthread_create 的主代码。我有三个 doit 函数,其中每个函数的 P 和 V 放置不同,或者根本没有 P 和 V。我的问题是,每个输出有何不同?更具体地说,每个 doit 函数可能的输出是什么?
到目前为止,我所知道的是 P(&sem) 会将 sem 值变为 0,而 V 会将值变为 1。但是,我很难解释它将如何影响代码。
到目前为止,我认为 doit 函数 #1 将导致 1 2 3,因为 printf 和 i=i+1 由 P(&sem) 和 V(&sem) 很好地保护。
此外,我认为 doit 函数 #2 的所有可能输出是 1, 2, 3/// 1, 3, 3/// 2, 2, 3/// 2, 3, 3/// 3, 3 , 3. 如果我错了,请纠正我。
但是,就可能的输出而言,我真的不确定在 doit 函数 #3 中多线程会发生什么。我将不胜感激任何形式的帮助,谢谢。
sem_t sem;
/* semaphore */
int main(){
int j;
pthread_t tids[3];
sem_init(&sem, 0,1);
for (j=0; j<3; j++) {
pthread_create(&tids[j], NULL, doit, NULL);
}
for (j=0; j<3; j++) {
pthread_join(&tids[j], NULL);
}
return 0;
}
doit# 1.
int i = 0;
void *doit(void *arg){
P(&sem);
i = i + 1;
printf("%d\n", i);
V(&sem);
}
doit #2.
int i = 0;
void *doit(void *arg){
P(&sem);
i = i + 1;
V(&sem);
printf("%d\n", i);
}
doit #3.
int i = 0;
void *doit(void *arg){
i = i + 1;
printf("%d\n", i);
}
解决方案
第一个程序将打印
1
2
3
它是唯一一个所有访问i
都由P / V正确保护的程序。
其他 2 个程序的行为是undefined,因为一个线程中的写入可能与另一个线程中的读取同时发生,并且根据C11 5.1.2.4p25:
- 如果程序的执行包含不同线程中的两个冲突操作,则该程序的执行包含数据竞争,其中至少一个不是原子的,并且两者都不会在另一个之前发生。任何此类数据竞争都会导致未定义的行为。
- 如果其中一个修改内存位置而另一个读取或修改相同的内存位置,则两个表达式求值会发生冲突。
通常这类作业要求找出 2 和 3 之间的差异。他们错了。从 C 的角度来看,您已经打开了潘多拉魔盒,一切皆有可能。
推荐阅读
- python - 关键 - 在 Travis CI 中运行时出错| pytest
- jquery - 如何使用jquery从json文件中获取每个值的计数
- java - 这
groupByKey(...) 中的类在其成员中有一个 Map。groupByKey 操作因“不可比较”问题而失败 - sql-server - 无法为 C# 应用程序的远程桌面创建连接字符串
- ios - xcode swift中的Webview
- java - 在 Eclipse IDE 中导入并运行一个 maven 项目
- python - 确定 unicode 字符是否存在于 unicode 子集中
- c++ - 获取字符串大小的各种方法之间的比较
- python - plotly 4.1没有情节
- docker - Docker Image推送到谷歌容器注册表不起作用