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

标签 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

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/

相关文章:

c - Unix 服务器客户端连接 : Connection refused

串行队列中的 iOS 网络请求

c# - .NET 运行时是否调用过 Thread.Abort()?

cocoa - 拖动跟踪期间的读/写访问、POSIX 权限和沙箱

python - 调用Python脚本时, "./script.py"和 "python script.py"有什么区别

c - 如何使用 Xcode 将参数传递给 c 控制台程序?

c - 阿杜诺 C : undefined reference to `readArms()'

c++ - c++11的线程,用new创建

Clang 无法编译 c11 程序,引用 "implicit declaration is illegal in c99"

c++ - 程序终止时保证文件删除 (C/C++)