Pthread поведение C ++ - PullRequest
0 голосов
/ 19 мая 2018

Я пробовал базовую программу pthreads / mutex:

#include<iostream>
#include<pthread.h>

using namespace std;

pthread_mutex_t mutex;

void* PrintHello(void *t)
{
    int i = reinterpret_cast<int>(t);
    pthread_mutex_lock(&mutex);
    cout<<"Hello, World thread <"<<i<<">!"<<endl;
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}

int main()
{
    pthread_t threadId[5];
    pthread_mutex_init(&mutex, NULL);

    for(int i = 0; i < 5; i ++)
    {
        int rc = pthread_create(&threadId[i], NULL, PrintHello, reinterpret_cast<void *>(i + 1));
    }

    return 0;
}

И я получаю следующий вывод:

Выполнение 1:

Hello, World thread <1>!
Hello, World thread <2>!
Hello, World thread <3>!
Hello, World thread <4>!
Hello, World thread <4>!
Hello, World thread <5>!

Выполнение 2:

Hello, World thread <1>!
Hello, World thread <2>!
Hello, World thread <3>!
Hello, World thread <4>!
Hello, World thread <5>!
Hello, World thread <5>!

Я ожидал, что всегда будет пять «Привет, мир!»печатает как вывод этой программы, но я вижу разные.Кто-нибудь может сказать мне, почему?

1 Ответ

0 голосов
/ 22 мая 2018

Когда основной поток возвращается из функции main, он завершает процесс как при вызове функции exit.Согласно документации , он сбрасывает stdout:

Все открытые потоки stdio (3) сбрасываются и закрываются.

Возможночто, поскольку вы не присоединяетесь к своим потокам, основные потоки сбрасывают stdout, в то время как другой поток все еще пишет в него.Поскольку очистка выполняется в деструкторе std::cout, нет необходимости использовать блокировку как обычно (поскольку использование разрушенного объекта является неопределенным поведением).

Также обратите внимание, что std::endl оба добавляют символ новой строки впоток и сбрасывает его.

Итак, представьте следующую последовательность:

  1. Потоки 1-4 печатают свое сообщение и сбрасывают его.
  2. Поток 5 печатает свое сообщение.
  3. Основной поток выходит и очищает поток, это делается без удержания обычной внутренней блокировки std::cout.
  4. Поток 5 начинает сбрасывать std::cout, снова сбрасывая то же сообщение, что и в шаге# 3.
...