pthread_cond_signal 不会立即取消阻塞 pthread_cond_wait 线程
pthread_cond_signal doesn't unblock pthread_cond_wait thread immediately
我观察到一种行为似乎与 pthread_cond_signal
和 pthread_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,在缓存中很热等,在现在未阻塞的线程开始做任何事情之前,它可能有足够的时间做一些事情。
在你上面的例子中,如果你不想跳过消息,也许你正在寻找的是类似于生产者-消费者队列的东西,可能由环形缓冲区支持。
我观察到一种行为似乎与 pthread_cond_signal
和 pthread_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,在缓存中很热等,在现在未阻塞的线程开始做任何事情之前,它可能有足够的时间做一些事情。
在你上面的例子中,如果你不想跳过消息,也许你正在寻找的是类似于生产者-消费者队列的东西,可能由环形缓冲区支持。