信号量中的P(&sem)和V(&sem)如何影响代码?

时间:2019-06-08 14:11:36

标签: c linux multithreading pthreads semaphore

我有这个主要代码,它以函数“ 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 个答案:

答案 0 :(得分:0)

第一个程序将打印

1
2
3

这是唯一受 P / V 正确保护对i的所有访问的程序。

其他2个程序的行为未定义,因为一个线程中的写入可能与另一线程中的读取同时发生,并且根据{{3} }:

  
      
  1. 如果程序的执行在不同的线程中包含两个冲突的动作,则其中至少一个不是原子的,并且两个动作都没有发生在另一个线程上,则该程序的执行将引起数据争用。任何此类数据争用都会导致未定义的行为。
  2.   

C11 5.1.2.4p25

  
      
  1. 如果两个表达式求值之一修改一个内存位置,而另一个表达式读取或修改了相同的内存位置,则冲突。
  2.   

通常,这类作业要求找出2与3之间的差异。这是错误的。从C角度来看,您已经打开了Pandora的盒子,一切皆有可能。