【问题标题】:the while loop does not stop when the condition has already been met当条件已经满足时,while循环不会停止
【发布时间】:2019-05-16 23:49:39
【问题描述】:

在我的代码中,我想一个一个地创建三个线程。所以我使用一个全局变量来控制它。但它不像我设计的那样工作。它在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同时(1!= startb); (gdb) bt

0 0x000000000040068b in main (argc=, argv=) at pthread.c:57 (gdb) p startb $1 = 1 (gdb) bt

0 0x000000000040068b in main (argc=, argv=) at 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

谁能告诉我原因?

【问题讨论】:

  • 请添加 startb 的声明,以便我们更好地提供帮助。
  • @iosi G startb 是一个全局变量。声明已添加。
  • 关于:void printB(void* para) posix 线程的签名是void * printB( void* para) 注意返回类型是void* 而不是void
  • OT:在main()不使用参数时,使用签名避免编译器对未使用参数的两次警告:int main( void )
  • 发布的代码会导致编译器输出许多警告和错误消息。编译时,始终启用警告,然后修复这些警告。 (对于gcc,至少使用:-Wall -Wextra -Wconversion -pedantic -std=gnu11)注意其他编译器使用不同的选项来执行相同的操作

标签: c


【解决方案1】:

您不能使用简单变量进行线程间通信。按照目前的情况,编译器会在循环中看到它

while (1 != startb); /*block here*/

startb 的值永远不会被修改,因此会合法地在内部将其重写为

if( 1 != startb ){
    while( true );
}

等待某个外部设置标志的循环称为Spinlock,正确的自旋锁实现必须小心使用Atomic Semanticity@987654323 @

但是,对于您打算做的事情,正确的选择是使用 Condition Variable,这是一种完全受到 pthreads 支持的构造,您已经尝试使用它,但是它不正确。

【讨论】:

  • 啊,我明白了。非常感谢。
猜你喜欢
  • 2019-01-29
  • 2013-11-22
  • 1970-01-01
  • 1970-01-01
  • 2016-03-14
  • 2020-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多