цикл while не останавливается, когда условие уже выполнено - PullRequest
0 голосов
/ 16 декабря 2018

В моем коде я хочу создать три потока один за другим.Поэтому я использую глобальную переменную для управления этим.Но это не работает, как я проектирую.Он заблокирован на время цикла.Вот мой код:

#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 в основном (argc =, argv =) в pthread.c: 57 57 while (1! = Startb);(gdb) bt

0 0x000000000040068b в основном (argc =, argv =) в pthread.c: 57 (gdb) p startb $ 1 = 1 (gdb) bt

0 0x000000000040068b в основном (argc =, argv =) at pthread.c: 57 (gdb) c

Продолжение.

Стек вызовов этих потоков:

main:

[<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

Может кто-нибудь сказать мне причину?

1 Ответ

0 голосов
/ 16 декабря 2018

Вы не можете использовать простые переменные для связи между потоками.Как есть, компилятор увидит, что в цикле

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

значение startb никогда не изменяется, и, следовательно, юридически перепишет его внутренне в

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

Цикл, ожидающий некоторого установленного извне флага, называется Спинлок , и правильная реализация спин-блокировки должна позаботиться об использовании Атомная семантика и Барьеры памяти .

Однако для того, что вы собираетесь делать, правильным выбором является использование Переменная условия , конструкция, которая отлично поддерживается pthreads, которую вы уже пытаетесь использовать, но делаете это неправильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...