【发布时间】:2013-05-27 04:37:51
【问题描述】:
我目前正在使用条件变量来同步两个线程 (pthread),并且遇到了一个意外的行为,即使我已经验证了一个线程已经在等待某个条件,但当另一个线程发出该条件的信号时它不会唤醒.
值得注意的是,我已经在桌面环境中运行了它,并且它按预期运行,但是当我使用 uclibc 在嵌入式环境中运行程序时会出现这个问题。
为了进行故障排除,我将我的代码剥离为仅执行锁定/解锁/信号的两个线程,如下所示:
#include <stdio.h>
#include <pthread.h>
#include <stdbool.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t condition2 = PTHREAD_COND_INITIALIZER;
bool predicate1 = false;
bool predicate2 = false;
static void * ThreadFunc2(void * arg) {
sleep(1); // For testing purposes, ensures this thread is run after Thread1
pthread_mutex_lock(&mutex2);
while(1) {
pthread_mutex_lock(&mutex1);
// Do some work - Eg receive some data from a socket
predicate1 = false;
pthread_cond_signal(&condition1);
pthread_mutex_unlock(&mutex1);
predicate2 = true;
while(predicate2 == true)
pthread_cond_wait(&condition2, &mutex2);
// Do some more work - Eg send response data to socket
}
}
static void * ThreadFunc1(void * arg) {
int result;
pthread_mutex_lock(&mutex1);
while(1) {
predicate1 = true;
while(predicate1 == true)
pthread_cond_wait(&condition1, &mutex1);
// Do some work - Eg process data on the socket and prepare response data to be sent
pthread_mutex_lock(&mutex2);
predicate2 = false;
pthread_cond_signal(&condition2);
pthread_mutex_unlock(&mutex2);
}
}
int main(int argc, char * argv[]) {
pthread_t thread1Id, thread2Id;
pthread_create(&thread1Id, NULL, ThreadFunc1, NULL);
pthread_create(&thread2Id, NULL, ThreadFunc2, NULL);
while(1) {
sleep(1);
}
return 0;
}
如果我排除与 mutex2/condition2/predicate2 相关的所有语句,这两个线程将按预期协同工作。
使用上面列出的代码,在很短的时间后(由于所有工作都已被剥离,每个循环运行得非常快)ThreadFunc1 中的 condition1 等待不会唤醒,即使它由 Threadfunc2 发出信号,导致应用程序正在运行停止。
为了帮助我进行调试,我重新定义了 pthread_* 函数,以便在调用实际 pthread_* 函数之前使用匹配的行号将消息打印到标准输出。这使我能够跟踪每个 pthread 操作的流程,并验证信号是否正在发送到已经等待的状态。
任何人都可以帮助我阐明上述实施中可能存在的任何潜在问题吗?
提前感谢您的任何建议。
【问题讨论】:
-
您的示例代码从不将
predicate2设置为false。 -
我添加了 @caf 所指出的缺失的 predicate2 语句 - 谢谢。不幸的是,问题仍然存在。
-
你能发布完整的测试程序(听起来应该不会更多),用于构建程序的命令以及有关使用的平台和工具版本的信息?我无法通过添加足够的脚手架来运行线程和几个
puts()调用来确保正在取得进展。这是在带有 gcc 4.6.1 的 x86 Linux 3.0 上。 -
我开始怀疑是否是由于使用我的嵌入式板支持包(使用 buildroot 的 BSP)构建的工具链造成的。我的平台是基于 m68k 的,使用 uclibc 0.9.31 和 gcc 4.4.1。我在另一个较旧的平台(基于 avr32,使用 uclibc 0.9.29 和 gcc 4.2.1)上进行了测试,问题没有重现。
-
@wei:你可能是对的。您是否将
-pthread选项传递给gcc? (注意:这是-pthread,与-lpthread不同)。如果您可以使用最新版本的uclibc重现它,您可以将其报告为错误。
标签: c linux multithreading pthreads