C POSIX线程的互斥/条件根据变量的存在位置而有所不同

时间:2012-11-24 00:22:36

标签: c multithreading posix mutex

我看到C POSIX线程中互斥/条件的意外行为取决于互斥和条件变量是否在结构中的全局范围(有效)中设置(有时可以工作)。

我在Mac上编程,然后在Linux机器上运行相同的代码。我复制了此示例中的代码,该代码在两台计算机中按预期工作:http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Fapis%2Fusers_73.htm 此示例在全局范围内具有pthread_mutex_tpthread_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

这是Linux上的输出(不起作用)

Create 5 threads
Thread blocked // Hangs here forever, other threads can't lock mutex

有谁知道为什么会这样?我承认我不是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");
}

1 个答案:

答案 0 :(得分:2)

问题是名为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));

但是,你有几个没有强制转换的调用(因此编译器应该大声抱怨)。我开始认为这可能是一个错误的红色鲱鱼。