我看到 C POSIX 线程中的互斥量/条件出现意外行为,具体取决于互斥量和条件变量是否设置在全局范围(有效)或结构(有时有效)中。
我在 Mac 上编程,然后在 Linux 机器上运行相同的代码。我从这个例子中复制了代码,它在两台机器上都按预期工作:http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Fapis%2Fusers_73.htm
此示例在全局范围内具有 pthread_mutex_t
和 pthread_cond_t
:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
...
pthread_mutex_lock(&mutex);
...
但是,如果我将其更改为将 cond 和 mutex 存储在结构中,它可以在 Mac 上运行,但不能在 Linux 上运行。
以下是我所做更改的概述:
typedef struct _test_data_t {
pthread_mutex_t cond;
pthread_cond_t mutex;
} test_data_t;
...
pthread_mutex_lock(&(test_data->mutex));
...
这是我在 Mac 上得到的输出(有效)
Create 5 threads Thread blocked Thread blocked Thread blocked Thread blocked Thread blocked Wake up all waiting threads... Wait for threads and cleanup Main completed
Here is the output on Linux (which does not work)
Create 5 threads Thread blocked // Hangs here forever, other threads can't lock mutex
Does anyone know why this might be happening? I will admit that I am not a C expert so I don't know what could have happened in the switch from using a global variable to a struct variable.
Thanks in advance for your help.
Here is the code (with some error checking stripped out for brevity):
typedef struct _test_data_t {
int conditionMet;
pthread_mutex_t cond;
pthread_cond_t mutex;
} test_data_t;
void *threadfunc(void *parm)
{
int rc;
test_data_t *test_data = (test_data_t *) parm;
rc = pthread_mutex_lock((pthread_mutex_t *)&(test_data->mutex));
while (!test_data->conditionMet) {
printf("Thread blocked\n");
rc = pthread_cond_wait(&test_data->cond, &test_data->mutex);
}
rc = pthread_mutex_unlock(&test_data->mutex);
return NULL;
}
void runThreadTest() {
int NTHREADS = 5;
int rc=0;
int i;
// Initialize mutex/condition.
test_data_t test_data;
test_data.conditionMet = 0;
rc = pthread_mutex_init(&test_data.mutex, NULL);
rc = pthread_cond_init(&test_data.cond, NULL);
// Create threads.
pthread_t threadid[NTHREADS];
printf("Create %d threads\n", NTHREADS);
for(i=0; i<NTHREADS; ++i) {
rc = pthread_create(&threadid[i], NULL, threadfunc, &test_data);
}
sleep(5);
rc = pthread_mutex_lock(&test_data.mutex);
/* The condition has occurred. Set the flag and wake up any waiting threads */
test_data.conditionMet = 1;
printf("Wake up all waiting threads...\n");
rc = pthread_cond_broadcast(&test_data.cond);
rc = pthread_mutex_unlock(&test_data.mutex);
printf("Wait for threads and cleanup\n");
for (i=0; i<NTHREADS; ++i) {
rc = pthread_join(threadid[i], NULL);
}
pthread_cond_destroy(&test_data.cond);
pthread_mutex_destroy(&test_data.mutex);
printf("Main completed\n");
}
最佳答案
问题是名为mutex
的成员是一个pthread_cond_t
而名为cond
的成员是一个pthread_mutex_t
.不必要的强制转换可能会掩盖这一事实。
typedef struct _test_data_t {
int conditionMet;
pthread_mutex_t cond; // <-- poorly named
pthread_cond_t mutex; // <-- poorly named
} test_data_t;
线程函数中的这一行不需要强制转换:
rc = pthread_mutex_lock((pthread_mutex_t *)&(test_data->mutex));
但是,您有几个没有转换的调用(因此编译器应该大声提示这些)。我开始认为这可能是一个转移注意力的错字。
关于C POSIX 线程的互斥锁/条件根据变量所在位置的不同而不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13537174/