【问题标题】:How to reset variable after last thread call?最后一次线程调用后如何重置变量?
【发布时间】:2016-12-10 22:51:54
【问题描述】:

我一直在尝试学习 pthreads,使用 mutex 和 cond,但我不知道如何仅在使用它的最后一个线程不再需要它之后重置变量。

我有以下代码:

int i = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;

int test() {
  if (i == 0) {
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
  }
  pthread_mutex_lock(&mutex);
  ++i;

  if (i % 5 != 0) {
    pthread_cond_wait(&cond, &mutex);
  }

  else {
    pthread_cond_broadcast(&cond);
  }

  int j = i;

  i = 0; /* problem line */
  pthread_mutex_unlock(&mutex);
  //i = 0; /* tried here too */

  return j;
}

我有多个线程调用这个test() 方法。

前4个线程会一直等到第5个被调用,然后所有5个线程都会返回5。但是 6th+ 会返回 '6','7',... 等等,我想重置 i 变量i = 0,所以计数会重新开始。

我想再做一个 thread_cond_t 让线程等到所有 j = i 完成。但我认为这是不对的(或至少是不必要的)。

实际输出是(由于线程,顺序未定):

0
0
0
0
5
0
0
0
5

我希望他们都是5s。

编辑:我将j 设为全局,i 在广播后进行了修改,到目前为止它一直有效:

int i = 0, j;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

int test() {
  pthread_mutex_lock(&mutex);
  ++i;

  if (i % 5 != 0) {
    pthread_cond_wait(&cond, &mutex);
  } else {
    pthread_cond_broadcast(&cond);
    j = i;
  }
  i = 0;
  pthread_mutex_unlock(&mutex);

  return j;
}

此代码在达到 5 后成功重置变量,并在所有线程上打印该值,但是当我尝试多个线程时,我似乎遇到了数据争用。

【问题讨论】:

  • 你确定第一个线程可以在第二个线程启动前调用2个init函数、锁和增量吗?
  • 实际上,我也有同样的疑问,但无法猜测另一种方法来初始化 mutex 和 cond 一次,到目前为止我还没有遇到过问题(多次尝试代码),但是欢迎提供见解。
  • 可以在启动线程之前调用init函数吗?你也可以使用初始化器PTHREAD_MUTEX_INITIALIZER。其余的代码看起来没问题。您可能会两次初始化互斥锁,从而调用未定义的行为。
  • 我无法在启动线程之前初始化 init() 函数,另一个函数(不可编辑)直接调用test() 方法。如您所说,将尝试 mutex_initializer 。谢谢。
  • @JonathanLeffler 你是对的,我已经更改了代码,现在将编辑我的帖子。现在它按预期工作,感谢 mch 和 JonathanLeffer。我有一个新问题 ;(,当我测试大量线程时它失败了,似乎我有数据竞争问题,我不确定如何解决它。

标签: c pthreads mutex


【解决方案1】:

此代码在达到 5 后成功重置变量,并在所有线程上打印该值,但是当我尝试多个线程时,我似乎遇到了数据争用。

使用编辑后的代码,考虑以下事件过程:四个线程在pthread_cond_wait 中等待,第五个线程刚刚通过pthread_cond_broadcast(导致前四个在mutex 上挂起,然后从pthread_cond_wait 返回),并且第六个线程已经在pthread_mutex_lock 中等待。现在在设置i = 0 后,第五次通过pthread_mutex_unlock 并说第六次以++i 继续,将i 设置为1,然后在pthread_cond_wait 中等待(导致@987654331 @ 开锁)。然后前四个线程之一恢复并通过i = 0,因此计数器i 被过度重置。
要纠正这个问题,请仅在执行pthread_cond_broadcast 的线程中重置i,即。 e.改变

  }
  i = 0;

    i = 0;
  }

(将i = 0 移动到else { pthread_cond_broadcast 块中)。

【讨论】:

    猜你喜欢
    • 2021-02-06
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-18
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    相关资源
    最近更新 更多