使用mutex进行pthread会产生随机答案

时间:2013-04-04 12:46:03

标签: c pthreads mutex

我写了一个简单的pthread代码

#include <pthread.h>
#include <stdio.h>
#include <math.h>

#define ITERATIONS 500

// A shared mutex
pthread_mutex_t mutex;
int target;

void* opponent(void *arg)
{
  int i;
  printf("opp, before for target=%d\n", target);
  pthread_mutex_lock(&mutex);
  for(i = 0; i < ITERATIONS; ++i)
  {
    target++;
  }
  pthread_mutex_unlock(&mutex);
  printf("opp, after for target=%d\n", target);

  return NULL;
}

int main(int argc, char **argv)
{
  pthread_t other;

  target = 5;

  // Initialize the mutex
  if(pthread_mutex_init(&mutex, NULL))
  {
    printf("Unable to initialize a mutex\n");
    return -1;
  }

  if(pthread_create(&other, NULL, &opponent, NULL))
  {
    printf("Unable to spawn thread\n");
    return -1;
  }

  int i;
  printf("main, before for target=%d\n", target);
  pthread_mutex_lock(&mutex);
  for(i = 0; i < ITERATIONS; ++i)
  {
    target--;
  }
  pthread_mutex_unlock(&mutex);
  printf("main, after for target=%d\n", target);

  if(pthread_join(other, NULL))
  {
    printf("Could not join thread\n");
    return -1;
  }

  // Clean up the mutex
  pthread_mutex_destroy(&mutex);

  printf("Result: %d\n", target);

  return 0;
}

然后我用这个命令编译

gcc -pedantic -Wall -o theaded_program pth.c -lpthread

但是,每次运行程序时,我都会得到不同的结果!!

 $ ./theaded_program
 main, before for target=5
 main, after for target=-495
 opp, before for target=5
 opp, after for target=5
 Result: 5

 $ ./theaded_program
 main, before for target=5
 opp, before for target=5
 opp, after for target=5
 main, after for target=-495
 Result: 5

2 个答案:

答案 0 :(得分:2)

当互斥锁被锁定且他们正在访问printf()时,target语句不会被执行:

printf("opp, before for target=%d\n", target);
pthread_mutex_lock(&mutex);

这意味着一个线程可能会更改target的值,而另一个线程正在尝试读取它(在printf()中)。移动锁定互斥锁时要执行的printf()语句:

pthread_mutex_lock(&mutex);
printf("opp, before for target=%d\n", target);
/* snip */
printf("opp, after for target=%d\n", target);
pthread_mutex_unlock(&mutex);

这将阻止target被一个线程读取并被另一个线程同时修改。但是,无法保证哪个线程首先获取互斥锁。

答案 1 :(得分:1)

此结果符合预期,您的代码保证主要和对手没有做

for(i = 0; i < ITERATIONS; ++i)
{
  target--; //or ++ for the opponent
}

同时。

printf不受互斥锁的任何保护。为避免这种情况,请在互斥锁/解锁

中插入printf