我正在练习一些多线程程序,但我无法弄清楚这个输出背后的逻辑。
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
int print_message(void* ptr);
int main()
{
pthread_t thread1,thread2;
char *mesg1 = "Thread 1";
char *mesg2 = "Thread 2";
int iret1, iret2;
pthread_create(&thread1, NULL, print_message, (void *)mesg1);
pthread_create(&thread2, NULL, print_message, (void *)mesg2);
pthread_join(thread1,(void*)&iret1 );
pthread_join(thread2, (void*)&iret2);
printf("Thread 1 return : %d\n", (int)iret1);
printf("Thread 2 return : %d\n", (int)iret2);
return 0;
}
int print_message(void *ptr)
{
char *mesg;
static int i=0;
mesg = (char *)ptr;
printf("%s\n",mesg);
i++;
return ((void*)i);
}
我期待输出
Thread 1
Thread 2
Thread 1 return : 1
Thread 2 return : 2
但是我得到了输出
Thread 1
Thread 2
Thread 1 return : 0
Thread 2 return : 2
有些人可以向我澄清一下吗?如果pthread函数的使用有任何错误,请指出。
答案 0 :(得分:4)
变量i
在两个线程之间共享,因为它是static
。在多个线程之间修改变量的行为是未定义的,因此,实际上,在获得编译器没有义务将其提供给您的意义上,您获得的输出和您想要获得的输出都是“错误的”。事实上,我能够根据我使用的优化级别来改变输出,并且毫无疑问它会根据平台而有所不同。
如果要修改i
,则应使用互斥锁:
int print_message(void *ptr)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char *mesg;
static int i=0;
int local_i;
mesg = (char *)ptr;
printf("%s\n",mesg);
if (pthread_mutex_lock(&mutex) == 0) {
local_i = ++i;
pthread_mutex_unlock(&mutex);
}
return ((void*)local_i);
}
如果您不使用互斥锁,则永远不会确定以获得您认为应该获得的输出。
答案 1 :(得分:3)
有几本关于多线程的好书。我觉得很有意思Butenhof's "Programming with Posix threads",但最近出现的书很多。
您是否在网上阅读了其中任何内容或pthreads tutorial好文章?
基本上,每个程序源代码线程可能无法像您期望的那样直观地查看内存。 (cache coherence,multi-processing,memory model,C11 ...)
实际上,对线程之间共享的数据的任何访问都应受synchronization原语的保护,例如mutexes或rwlocks
在开始编码之前,您真的应该了解这些问题。调试多线程程序是一场噩梦(非确定性,heisenbugs)。