С++ 11 простой пример

Я новичок в С++, и я изучал некоторые кросс-платформенные учебники потоков С++. Я смотрел на это: http://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/

и пытался выполнить следующий код:

#include <iostream>
#include <thread>

static const int num_threads = 10;

//This function will be called from a thread

void call_from_thread(int tid) {
    std::cout << "Launched by thread " << tid << std::endl;
}

int main() {
    std::thread t[num_threads];

    //Launch a group of threads
    for (int i = 0; i < num_threads; ++i) {
        t[i] = std::thread(call_from_thread, i);
    }

    std::cout << "Launched from the main\n";

    //Join the threads with the main thread
    for (int i = 0; i < num_threads; ++i) {
        t[i].join();
    }

    return 0;
}

Выход, который я получаю, следующий, и я не понимаю, почему:

[email protected]:~/Desktop$ ./ref
Launched by thread Launched by thread Launched by thread Launched by thread Launched by thread 201
Launched by thread 5

Launched by thread 6
4
Launched by thread 7
3

Launched by thread 8
Launched from the main
Launched by thread 9

Я понимаю, что цифры случайны каждый раз, но иногда я не получаю никаких номеров, и мне интересно, почему?

Ответы

Ответ 1

Они все там. Они просто искалечены, потому что вывод консоли происходит в неопределенно случайных порядках.

В частности, посмотрите на конец первой строки вывода.

Ответ 2

все, что вам нужно сделать, это добавить мьютекс и заблокировать его в правильном положении:

std::mutex mtx;

-

void call_from_thread(int tid) {
    mtx.lock();
-----------------------------------------------------------
    std::cout << "Launched by thread " << tid << std::endl;
-----------------------------------------------------------
    mtx.unlock();
}

-

mtx.lock();
-----------------------------------------------------------
std::cout << "Launched from the main\n";
-----------------------------------------------------------
mtx.unlock();

обратитесь к этому вопросу

Ответ 3

В IO (cout) есть условие гонки в

std::cout << "Launched by thread " << tid << std::endl;

На самом деле, нет гарантии для последовательности cout ( "Запущен по потоку", tid, std:: endl). И он ведет себя так:

std::cout << "Launched by thread " ;
cout<< tid ;
cout<< std::endl;

Вы можете изменить call_from_thread на:

void call_from_thread(int tid) {
    std::cout << std::string("Launched by thread " + std::to_string(tid) + "\n");
}

Следующий пункт находится в

t[i] = std::thread(call_from_thread, i);

При создании потока во время создания будет вызываться функция call_from_thread.

Так что лучше перемещать

std::cout << "Launched from the main\n";

Перед

//Launch a group of threads
for (int i = 0; i < num_threads; ++i) {
    t[i] = std::thread(call_from_thread, i);
}

Вы также можете использовать держатели:

mutex g_i_mutex;  // protects cout

void call_from_thread(int tid) {
    lock_guard<mutex> lock(g_i_mutex);
    cout << "Launched by thread " ;
    cout<< tid ;
    cout<< std::endl;
} 

Ответ 4

Промывочный поток должен сделать трюк:)

Следующая строка: std::cout << "Launched by thread " << tid << std::endl;

Изменить на: std::cout << "Launched by thread " << tid << std::endl << std::flush;