在我的代码中,我想一个一个地创建三个线程。所以我使用一个全局变量来控制它。但这在我设计时不起作用。它在while循环中被阻止。这是我的代码:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
int startb = 0, startc=0;
.......
int main(int argc, char* argv[]){
pthread_t ida,idb,idc;
int result;
pthread_key_create(&stKey, TsdFree);
result = pthread_create(&idb, NULL, (void*)printB, NULL);
if(0 != result)
{
printf("create thread B error\n");
}
while (1 != startb); /*block here*/
result = pthread_create(&idc, NULL, (void*)printC, NULL);
........
}
线程B:
void printB(void* para)
{
for(int i=0; i<2;++i)
{
pthread_mutex_lock(&mutex);
startb = 1;
pthread_cond_wait(&conda, &mutex);
pthread_mutex_unlock(&mutex);
printf("B\n");
pthread_mutex_lock(&mutex);
pthread_cond_signal(&condb);
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}
我使用gdb查看startb变量的值。事实证明startb的值已经是1:
使用libthread_db启用线程调试]使用主机libthread_db 库“ /lib/x86_64-linux-gnu/libthread_db.so.1”。 0x000000000040068b 在pthread.c:57的main(argc =,argv =)中 57 while(1!= startb); (gdb)bt
0 0x000000000040068b在主线程(argc =,argv =)在pthread.c:57(gdb)p startb $ 1 = 1(gdb)bt
0 0x000000000040068b在主线程(argc =,argv =)在pthread.c:57(gdb)c
继续。
这些线程的调用堆栈:
主要:
[<0>] exit_to_usermode_loop+0x59/0xd0
[<0>] prepare_exit_to_usermode+0x77/0x80
[<0>] retint_user+0x8/0x8
[<0>] 0xffffffffffffffff
线程B:
[<0>] futex_wait_queue_me+0xc4/0x120
[<0>] futex_wait+0x10a/0x250
[<0>] do_futex+0x325/0x500
[<0>] SyS_futex+0x13b/0x180
[<0>] do_syscall_64+0x73/0x130
[<0>] entry_SYSCALL_64_after_hwframe+0x3d/0xa2
[<0>] 0xffffffffffffffff
有人可以告诉我原因吗?
答案 0 :(得分:5)
您不能在线程间通信中使用简单变量。就目前情况而言,编译器将在循环中看到
while (1 != startb); /*block here*/
startb
的值永远不会被修改,因此将合法在内部将其重写为
if( 1 != startb ){
while( true );
}
一个等待外部设置标志的循环称为 Spinlock ,正确的自旋锁实现必须小心使用 Atomic Semanticity 和< em> Memory Barriers 。
不过,对于您打算做的事情,正确的选择是使用 Condition Variable ,这是pthread很好地支持的结构,您已经尝试使用它,但是这样做不正确。