Я только начал читать о многопоточности и попытался написать очень простую программу на C++.
Проблема в том, что мои три потока пытаются печатать одновременно, что искажает вывод. Вывод каждый раз разный.
Чтобы решить эту проблему, я добавил 1-секундную задержку в каждом бесконечном цикле, что по большей части устранило проблему. Однако при каждом запуске одна строка выполняется раньше, чем должна выполняться другая (подробнее см. ниже).
Мой идеальный результат:
Calc1 Result: __
count1: __
Calc2 Result: __
count2: __
Calc3 Result: __
count3: __
И пусть это будет повторяться всегда
Мой код и несколько примеров различных выходных данных приведены ниже.
Код:
#include <iostream>
#include <thread>
using namespace std;
void calc1(int num) {
int count1 = 0;
while (true) {
printf(" Calc1 Result = %d\n", num + 1);
++count1;
printf("count1 = %d\n", count1);
this_thread::sleep_for(chrono::seconds(1));
}
}
void calc2(int num) {
int count2 = 0;
while (true) {
printf(" Calc2 Result = %d\n", num + 2);
++count2;
printf("count2 = %d\n", count2);
this_thread::sleep_for(chrono::seconds(1));
}
}
void calc3(int num) {
int count3 = 0;
while (true) {
printf(" Calc3 Result = %d\n", num + 3);
++count3;
printf("count3 = %d\n", count3);
this_thread::sleep_for(chrono::seconds(1));
}
}
int main()
{
thread one(calc1, 25);
thread two(calc2, 50);
thread three(calc3, 100);
one.join();
two.join();
three.join();
return 0;
}
Выводы:
Иногда вывод начинается с выполнения одной из функций, а иногда и другой.
Например, вот первые 12 строк вывода для 2 разных запусков.
1. Первые 6 строк здесь идеальны. Но тогда Calc3 запускается перед Calc1 и Calc2 в строках 7-12 этого вывода.
Calc1 Result = 26
count1 = 1
Calc2 Result = 52
count2 = 1
Calc3 Result = 103
count3 = 1
Calc3 Result = 103
Calc1 Result = 26
count1 = 2
count3 = 2
Calc2 Result = 52
count2 = 2
Здесь три вещи:
Во-первых, вывод отличается от моего первого запуска. (строки 1-6 одинаковые, далее разные)
Во-вторых, циклы снова выполняются в нежелательном порядке. Calc3, затем Calc2, затем Calc1 вместо 1 2 3.
В-третьих, результаты Calc3 и Calc2 отображаются вплотную друг к другу (строки 7, 8), но я хочу, чтобы результат и подсчет для каждого цикла отображались вплотную. Я знаю, что эту конкретную проблему можно исправить, объединив операторы printf результата и счетчика, но я предпочитаю отдельные операторы printf. Есть ли другой способ исправить это?
Calc1 Result = 26
count1 = 1
Calc2 Result = 52
count2 = 1
Calc3 Result = 103
count3 = 1
Calc3 Result = 103
Calc2 Result = 52
count2 = 2
count3 = 2
Calc1 Result = 26
count1 = 2
Кто-нибудь знает, должно ли это произойти? И если да, то почему это происходит?
Кроме того, если есть рекомендуемые ресурсы (видео, книги или статьи), пожалуйста, дайте ссылку на них.
Заранее спасибо :D
Потоки работают независимо, поэтому нет ожидаемого порядка вывода. Если вы хотите что-то упорядочить между потоками, вы должны сделать это явно. Например, вы можете реализовать сценарий производитель/потребитель, в котором потребитель берет результаты и распечатывает их.
Весь смысл многопоточности заключается в параллельной обработке, поэтому выполнение операций потоками по порядку противоречит тому, для чего они нужны. Возможно, вы не ищете многопоточное решение для своей проблемы, нет простого способа заставить потоки работать. Это побеждает цель.
И у вас есть 3 счетчика (
count1
,count2
иcount3
), которые вы увеличиваете на единицу, чтобы получить по 3 каждого числа. Если вы хотите синхронизировать события, вам нужно использовать некоторые примитивы синхронизации, такие какstd::mutex
иstd::condition_variable
. Три функцииcalc
также выглядят так, как будто их можно объединить в одну, которую вы вызываете 3 раза. пример