pthread_cond_signal 不会立即取消阻塞 pthread_cond_wait 线程

pthread_cond_signal doesn't unblock pthread_cond_wait thread immediately

我观察到一种行为似乎与 pthread_cond_signalpthread_cond_wait 的行为不一致(根据联机帮助页)。 man 3 pthread_cond_signal规定:

The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond).

这不够精确,也没有说明调用 pthread_cond_signal 的线程是否会同时将其时间返回给调度程序。

这是一个示例程序:

     1  #include <pthread.h>
     2  #include <iostream>
     3  #include <time.h>
     4  #include <unistd.h>
     5
     6  int mMsg = 0;
     7  pthread_mutex_t mMsgMutex;
     8  pthread_cond_t mMsgCond;
     9  pthread_t consumerThread;
    10  pthread_t producerThread;
    11
    12  void* producer(void* data) {
    13      (void) data;
    14      while(true) {
    15          pthread_mutex_lock(&mMsgMutex);
    16          std::cout << "1> locked" << std::endl;
    17          mMsg += 1;
    18          std::cout << "1> sending signal, mMsg = " << mMsg << "" << std::endl;
    19          pthread_cond_signal(&mMsgCond);
    20          pthread_mutex_unlock(&mMsgMutex);
    21      }
    22
    23      return nullptr;
    24  }
    25
    26  void* consumer(void* data) {
    27      (void) data;
    28      pthread_mutex_lock(&mMsgMutex);
    29
    30      while(true) {
    31          while (mMsg == 0) {
    32              pthread_cond_wait(&mMsgCond, &mMsgMutex);
    33          }
    34          std::cout << "2> wake up, msg: " << mMsg << std::endl;
    35          mMsg = 0;
    36      }
    37
    38      return nullptr;
    39  }
    40
    41  int main()
    42  {
    43      pthread_mutex_init(&mMsgMutex, nullptr);
    44      pthread_cond_init(&mMsgCond, nullptr);
    45
    46      pthread_create(&consumerThread, nullptr, consumer, nullptr);
    47
    48      std::cout << "starting producer..." << std::endl;
    49
    50      sleep(1);
    51      pthread_create(&producerThread, nullptr, producer, nullptr);
    52
    53      pthread_join(consumerThread, nullptr);
    54      pthread_join(producerThread, nullptr);
    55      return 0;
    56  }

这是输出:

starting producer...
1> locked
1> sending signal, mMsg = 1
1> locked
1> sending signal, mMsg = 2
1> locked
1> sending signal, mMsg = 3
1> locked
1> sending signal, mMsg = 4
1> locked
1> sending signal, mMsg = 5
1> locked
1> sending signal, mMsg = 6
1> locked
1> sending signal, mMsg = 7
1> locked
1> sending signal, mMsg = 8
1> locked
1> sending signal, mMsg = 9
1> locked
1> sending signal, mMsg = 10
2> wake up, msg: 10
1> locked
1> sending signal, mMsg = 1
1> locked
1> sending signal, mMsg = 2
1> locked
1> sending signal, mMsg = 3
...

似乎不​​能保证任何 pthread_cond_signal 确实会立即解除阻塞任何等待的 pthread_cond_wait 线程。同时,似乎任何数量的 pthread_cond_signal 都可以在第一个发行后丢失。

这真的是预期的行为还是我做错了什么?

这是预期的行为。 pthread_cond_signal 不会让出剩余的 运行 时间,但会继续到 运行。

是的,pthread_cond_signal 将立即解除阻塞(一个或多个)等待相应条件变量的线程。但是,这并不能保证所述等待线程将立即 运行。它只是告诉 OS 这个线程不再被阻塞,由 OS 线程调度程序决定何时启动它 运行。由于信号线程已经 运行ning,在缓存中很热等,在现在未阻塞的线程开始做任何事情之前,它可能有足够的时间做一些事情。

在你上面的例子中,如果你不想跳过消息,也许你正在寻找的是类似于生产者-消费者队列的东西,可能由环形缓冲区支持。