我在 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 上得到的输出(有效)
创建 5 个线程 线程阻塞 线程阻塞 线程阻塞 线程阻塞 线程阻塞 唤醒所有等待的线程... 等待线程和清理 主要完成
这是 Linux 上的输出(不起作用)
创建 5 个线程 线程阻塞 // 永远挂在这里,其他线程无法锁定互斥锁
有谁知道为什么会发生这种情况?我承认我不是 C 专家,所以我不知道从使用全局变量到结构变量的切换会发生什么。
在此先感谢您的帮助。
这是代码(为简洁起见,去掉了一些错误检查):
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");
}