Я не могу распечатать вывод на экране. Я использую сторону cppreference (GCC 12.1 (С++ 20 )) компилятор, есть ли тупиковая ситуация в приведенном ниже примере. Есть ли какой-нибудь онлайн-компилятор, который я могу использовать для проверки примеров такого типа?
#include <iostream>
#include <semaphore>
#include <thread>
#include <vector>
std::vector<int> myVec{};
std::counting_semaphore<1> prepareSignal(2); // (1)
void prepareWork()
{
myVec.insert(myVec.end(), {0, 1, 0, 3});
std::cout << "Sender: Data prepared." << '\n';
prepareSignal.release(); // (2)
}
void completeWork()
{
std::cout << "Waiter: Waiting for data." << '\n';
prepareSignal.acquire(); // (3)
myVec[2] = 2;
std::cout << "Waiter: Complete the work." << '\n';
for (auto i: myVec) std::cout << i << " ";
std::cout << '\n';
}
int main()
{
std::cout << '\n';
std::thread t1(prepareWork);
std::thread t3(completeWork);
std::thread t2(completeWork);
t1.join();
t3.join();
t2.join();
std::cout << '\n';
}
Если вы читали страницу cppreference, можете ли вы объяснить своими словами, как вы ожидаете, что counting_semaphore будет работать здесь? Поскольку инициализация уже неверна, см. предварительные условия здесь: en.cppreference.com/w/cpp/thread/counting_semaphore/…
А почему аргумент шаблона counting_semaphore меньше, чем аргумент конструктора?





Тупика нет, но у вас есть состояние гонки:
В completeWorkprepareSignal.acquire не блокирует выполнение (на основе документации по c++: «Когда счетчик равен нулю, функцияAcquire() блокируется до тех пор, пока счетчик не будет увеличен»). В этом случае счетчик установлен на 2, и нет никакого другого захвата.
Таким образом, программа может запуститься completeWork раньше, чем prepareWork, которая выполнит myVec[2] = 2;. Это вызывает неопределенное поведение, поскольку ваш вектор пуст.
Вы можете протестировать такие ошибки с помощью Address Sanitizer.
Посмотрите здесь живой пример, который подчеркивает эту проблему, добавляя 1-секундную задержку сна к prepareWork:
https://godbolt.org/z/YYsfq84bd
Выходные данные дезинфицирующего средства адреса точно сообщат вам, где ошибка!
Кроме того, дезинфектор потоков даст вам более четкую информацию о гонке данных и без необходимости выяснять, где проверить задержку: godbolt.org/z/zTqjnr6zE
Без взаимоблокировки, но с неопределенным поведением. Ни один из потоков не упорядочен должным образом. Семафоры не упорядочиваются.