pthread_cond_wait() 未释放互斥体的可能原因?

发布于 2024-11-27 09:19:37 字数 948 浏览 2 评论 0原文

我的程序似乎存在死锁问题。

基本上我有一个如下所示的类:

class Foo {
public:
  Foo();

  void bar();

private:
  void monitor();

  bool condition_;
  pthread_t monitor_;
  pthread_mutex_t mutex_;
  pthread_cond_t cv_;
};

Foo 的构造函数中,我在单独的线程(即 monitor_)中调用 monitor() 。此 monitor() 函数执行以下操作:

pthread_mutex_lock(&mutex_);
while (true) {
  while (!condition_) {
    pthread_cond_wait(&cv_, &mutex_);
  }
  // do something
  // and then setting condition_ to false
  condition_ = false;
}
pthread_mutex_unlock(&mutex_);

bar() 函数是 Foo 的唯一公共接口(不包括 ctor 和 dtor)。它还需要在执行时获取互斥锁。我的症状是 bar() 永远无法获取 mutex_。看起来 pthread_cond_wait() 没有按预期释放互斥锁。如果我禁用监视器线程(因此没有竞争条件),那么 bar() 可以毫无问题地运行到完成。

当然,上面的代码是我的真实代码的精简版本。实际上我认为这段代码没有逻辑错误,并且我正确使用了pthread。我怀疑是否还有其他原因导致这种僵局情况。有人能提供这方面的线索吗?谢谢!

My program is seemingly having a deadlock problem.

Basically I have a class that looks like this:

class Foo {
public:
  Foo();

  void bar();

private:
  void monitor();

  bool condition_;
  pthread_t monitor_;
  pthread_mutex_t mutex_;
  pthread_cond_t cv_;
};

In Foo's constructor, I invoke monitor() in a separate thread (namely monitor_). This monitor() function does the following:

pthread_mutex_lock(&mutex_);
while (true) {
  while (!condition_) {
    pthread_cond_wait(&cv_, &mutex_);
  }
  // do something
  // and then setting condition_ to false
  condition_ = false;
}
pthread_mutex_unlock(&mutex_);

The bar() function is the only public interface (excluding ctor and dtor) of Foo. It also needs to acquire the mutex in its execution. My symptom is that bar() can never acquire mutex_. It looks like pthread_cond_wait() does not release the mutex as it is supposed to do. And if I disable the monitor thread (thus no racing condition), then bar() can run to its completion without any problem.

Of course, the above code is a stripped-down version of my real code. Actually I think there is no logic error in this code and I'm using pthread correctly. I'm suspecting if there are any other causes for this deadlock situation. Can anyone give a clue on this? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

dawn曙光 2024-12-04 09:19:37

我会查看您的构造函数和 bar() 函数,并且可能会查看您是否意外复制了相关对象。我复制了您提供的类,以及我对其余部分如何运行的假设。下面的程序每秒唤醒一次,并向线程发出信号。

#include <pthread.h>
#include <iostream>

class Foo {
public:
  Foo() {
    condition_ = false;
    pthread_mutex_init(&mutex_, NULL);
    pthread_cond_init(&cv_, NULL);
    pthread_create(&monitor_, NULL,
           startFunc, this);
  }

  void bar() {
    pthread_mutex_lock(&mutex_);
    std::cout << "BAR" << std::endl;
    condition_ = true;
    pthread_cond_signal(&cv_);
    pthread_mutex_unlock(&mutex_);
  }

private:
  Foo(const Foo&) {};
  Foo& operator=(const Foo&) { return *this; };

  static void* startFunc(void* r) {
    Foo* f = static_cast<Foo*>(r);
    f->monitor();
    return NULL;
  }

  void monitor() {
    pthread_mutex_lock(&mutex_);
    while (true) {
      while (!condition_) {
    pthread_cond_wait(&cv_, &mutex_);
      }
      // do something
      // and then setting condition_ to false
      std::cout << "FOO" << std::endl;
      condition_ = false;
    }
    pthread_mutex_unlock(&mutex_);

  }

  bool condition_;
  pthread_t monitor_;
  pthread_mutex_t mutex_;
  pthread_cond_t cv_;
};


int main() {
  struct timespec tm = {1,0};
  Foo f;

  while(true) {
    f.bar();
    nanosleep(&tm, NULL);
  }

}

I would look at your constructor and the bar() function, and possibly if you've accidentally made a copy of the object in question. I've copied the classes you provided, and my assumptions on how the rest of it operates below. The program below wakes up every second, and signals the thread.

#include <pthread.h>
#include <iostream>

class Foo {
public:
  Foo() {
    condition_ = false;
    pthread_mutex_init(&mutex_, NULL);
    pthread_cond_init(&cv_, NULL);
    pthread_create(&monitor_, NULL,
           startFunc, this);
  }

  void bar() {
    pthread_mutex_lock(&mutex_);
    std::cout << "BAR" << std::endl;
    condition_ = true;
    pthread_cond_signal(&cv_);
    pthread_mutex_unlock(&mutex_);
  }

private:
  Foo(const Foo&) {};
  Foo& operator=(const Foo&) { return *this; };

  static void* startFunc(void* r) {
    Foo* f = static_cast<Foo*>(r);
    f->monitor();
    return NULL;
  }

  void monitor() {
    pthread_mutex_lock(&mutex_);
    while (true) {
      while (!condition_) {
    pthread_cond_wait(&cv_, &mutex_);
      }
      // do something
      // and then setting condition_ to false
      std::cout << "FOO" << std::endl;
      condition_ = false;
    }
    pthread_mutex_unlock(&mutex_);

  }

  bool condition_;
  pthread_t monitor_;
  pthread_mutex_t mutex_;
  pthread_cond_t cv_;
};


int main() {
  struct timespec tm = {1,0};
  Foo f;

  while(true) {
    f.bar();
    nanosleep(&tm, NULL);
  }

}
时间你老了 2024-12-04 09:19:37

我敢打赌,它在这里失败了:

while (!condition_) {
    pthread_cond_wait(&cv_, &mutex_);
}

让我们假设,条件为假。您进入 while 循环,在第一次运行中一切顺利,即您解锁互斥体并等待决策变量。是否会发生条件变量发生变化但布尔 条件 不变的情况?在这种情况下,您将使用未初始化的互斥体输入 pthread_cond_wait ,并且可能会发生未定义的行为...
我想如果您也展示 bar() 方法将会有所帮助。

另一个猜测是线程优先级。也许插入一个收益以使线程有更好的机会进行切换。

My bet is that it fails in here:

while (!condition_) {
    pthread_cond_wait(&cv_, &mutex_);
}

Let's assume, condition is false. You enter the while loop and in the first run everything goes fine, i.e. you unlock the mutex and wait on the decision variable. Can it happen that the condition variable changes but not the boolean condition ? In that case you would enter pthread_cond_wait with an uninitialized mutex and undefined behaviour can occur...
I guess it would help if you would show the bar() method as well.

Another guess would be thread priorities. Maybe insert a yield to give the threads a better chance to switch.

孤寂小茶 2024-12-04 09:19:37

如果您再次遇到这种情况,我遇到了非常类似的情况,我遇到了死锁,我期望 cond_wait 释放互斥体,以便其他线程可以锁定互斥体。

我的问题是,我已将互斥体设置为递归(使用 settype->PTHREAD_MUTEX_RECURSIVE_NP),并且在 cond_wait 调用之前错误地锁定互斥体两次。由于 cond_wait 仅解锁一次,因此互斥体仍然处于锁定状态。显而易见的解决方法是只锁定一次。另外,作为一个教训,除非确实需要,否则我不会使用递归互斥体设置。

In case you run into this again, I ran into a very similar situation where I was running into a deadlock, where I was expecting cond_wait to release the mutex so that other threads could lock the mutex.

My issue was that I had set the mutex as recursive (with settype->PTHREAD_MUTEX_RECURSIVE_NP) and was mistakenly locking the mutex twice before the cond_wait call. Since the cond_wait only unlocked it once, the mutex was still locked. The obvious fix was to only lock it once. Also, as a lesson learned, I won't be using the recursive mutex setting unless I really need to.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文