首页 > 解决方案 > 信号量中的 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);
     }

标签: clinuxmultithreadingpthreadssemaphore

解决方案


第一个程序将打印

1
2
3

它是唯一一个所有访问i都由P / V正确保护的程序。

其他 2 个程序的行为undefined,因为一个线程中的写入可能与另一个线程中的读取同时发生,并且根据C11 5.1.2.4p25

  1. 如果程序的执行包含不同线程中的两个冲突操作,则该程序的执行包含数据竞争,其中至少一个不是原子的,并且两者都不会在另一个之前发生。任何此类数据竞争都会导致未定义的行为。

C11 5.1.2.4p4

  1. 如果其中一个修改内存位置而另一个读取或修改相同的内存位置,则两个表达式求值会发生冲突。

通常这类作业要求找出 2 和 3 之间的差异。他们错了。从 C 的角度来看,您已经打开了潘多拉魔盒,一切皆有可能。


推荐阅读