【问题标题】:How do P(&sem) and V(&sem) in semaphore affect the code?信号量中的 P(&sem) 和 V(&sem) 如何影响代码?
【发布时间】:2019-10-23 17:15:39
【问题描述】:

我有这个以函数“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);
     }

【问题讨论】:

  • C 没有指定将在 2 或 3 中打印什么,由于数据竞争,一切皆有可能。但是,在 3 中存在写入竞赛,这可能意味着在实践中可能会发生比 2 更特殊的结果。
  • 因此我们可以肯定地说的唯一功能是第一个。

标签: c linux multithreading pthreads semaphore


【解决方案1】:

第一个程序将打印

1
2
3

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

另外两个程序的行为未定义,因为一个线程中的写入可能与另一个线程中的读取同时发生,并且根据C11 5.1.2.4p25

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

C11 5.1.2.4p4

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多