0 / 0 / 0
Регистрация: 24.01.2021
Сообщений: 1

Многопоточность. Не работает condition_variable

24.01.2021, 16:08. Показов 4597. Ответов 28

Студворк — интернет-сервис помощи студентам
Доброго времени суток!
Есть задание: Пользователь вводит строку с клавиатуры. Первой поток должен её принять и положить в файл и вновь потребовать от юзера строку. Второй поток должен взять строку из файла и вывести её на экран, после чего ждать, когда в файле появится новая строка. Потоки должны быть синхронизированы.
Собственно, проблема - condition.wait() не заставляет второй поток ждать вызова condition.notify_one(), как планировалось. Вместо этого все зависит от наличия this_thread::sleep_for(chrono::milliseco nds(1));. Как заставить работать условную переменную так, как того хочется?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#define _CRT_SECURE_NO_WARNINGS
#include <mutex>
#include <iostream>
#include<vector>
#include <thread>
#include <fstream>
#include <chrono>
#include <condition_variable>
using namespace std;
const int MAX_COUNTER = 20;
//condition_variable condition;
class UserInputTransformer
{
public:
 
    void prepare_buffer()
    {
        unique_lock<mutex> lock(simple_mutex);
        cout << "Введите строку:";
        cin >> buffer;
 
        ofstream out;
        out.open("buffer.txt");
        if (out.is_open())
        {
            out << buffer;
        }
        out.close();
 
        buffer.clear();
        ch = false;
        //condition.notify_one();
        lock.unlock();
        this_thread::sleep_for(chrono::milliseconds(1));
 
        ++counter;
        
        if (counter >= MAX_COUNTER)
        {
            return;
        }
 
        prepare_buffer();
    }
 
    void extract_buffer()
    {
        unique_lock<mutex> lock(simple_mutex);
 
        condition.wait(lock, [&] {
            return !ch;
            });
 
        ifstream fin;
        string buffer;
        fin.open("buffer.txt");
        if (!(fin.eof()))
        {
            fin >> buffer;
        }
        cout << "Строка из файла:" << buffer << endl;
 
        FILE* file;
        file = fopen("buffer.txt", "w");
        fclose(file);
        ch = true;
        lock.unlock();
 
        ++counter;
 
        if (counter >= MAX_COUNTER)
        {
            return;
        }
 
        extract_buffer();
    }//*/
 
    //MyClass();
    //~MyClass();
 
private:
    bool ch = true;
    int sum = 0;
    condition_variable condition;
    mutex simple_mutex;
    string buffer;
    int counter = 0;
};
;
 
int main()
{
    setlocale(LC_ALL, "rus");
 
 
    UserInputTransformer A;
 
 
    thread th1([&A]() {
        A.prepare_buffer();
        });
    thread th2([&A]() {
        A.extract_buffer();
        });
    th1.join();
    th2.join();//*/
 
}
Многопоточность для меня новая тема, поэтому какие-нибудь очевидные вещи могу упускать из виду, но похожую ситуацию(но с рабочими condition_variable) я встречал в обучающих материалах.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.01.2021, 16:08
Ответы с готовыми решениями:

C++11, потоки, std::condition_variable
Проблема в том, что в коде ниже сначала работает лишь поток th1, а затем только th2 (поток th1 бездействует). Хотелось бы, чтобы при...

Как устроен condition_variable::wait?
Всем привет, изучаю c_v стандартной библиотеки и возник вопрос что происходит когда condition_variable::wait захватывает поток и он не...

Не понятно как работает пример std::condition_variable::wait
Здравствуйте! Разбираюсь с std::condition_variable и не могу понять пример кода из cppreference.com. Вот он: #include &lt;iostream&gt;...

28
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,550
31.03.2021, 19:29
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от JeyCi Посмотреть сообщение
допустим, в момент, когда она дождалась своего условия, чтобы выйти из своего wait, она отпускает мьютекс...
да, я тоже почти так предположила... значит логика работает - только чуть подправить её надо - ! в момент, когда ожидать начинает! ещё только => отпускает мьютекс
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
wait(lock) разблокирует мьютекс
Добавлено через 18 минут
Цитата Сообщение от zayats80888 Посмотреть сообщение
knock_knock.wait(lck, [this]{ return !active || visitors; });
захват [this] меня смущал... не UB ли это... может правильнее [*this]... перелистала этот линк - поняла, что пока существует объект Gate в данном случае - bad_alloc, вероятно, не будет... опасалась его, т.к. this, полагаю, передаётся по ссылке в лямбду через [this]...
в общем, пока всё в объекте и он жив - всё норм должно быть... имхо
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
31.03.2021, 19:34
Цитата Сообщение от JeyCi Посмотреть сообщение
захват [this] меня смущал... не UB ли это... может правильнее [*this].
[*this] создаст копию объекта
1
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,550
31.03.2021, 19:46
да и это, конечно, лучше... в случае если thread переживёт this - то не будет dangling reference... логично... НО нелогично, чтобы поток запущенный объектом и ему принадлежащий, пережил сам объект ... а вот пишу и думаюю... если мы его std::move -- то, конечно, и пережить может... благодарю за пример и пояснения, на практике всегда быстрее доходит

Добавлено через 5 минут
просто удивилась, что zayats80888 написал [this] - значит и так можно -
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
31.03.2021, 19:46
Цитата Сообщение от JeyCi Посмотреть сообщение
да и это, конечно, лучше... в случае если thread переживёт this - то не будет dangling reference... логично... НО нелогично, чтобы поток запущенный объектом и ему принадлежащий, пережил сам объект ... а вот пишу и думаюю... если мы его std::move -- то, наверно, и пережить может...
Там нюансов дофига и больше. В целом, надо чётко контролировать время жизни объёкта и время работы потока, с учётом виртуальных функций.
0
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,550
31.03.2021, 19:49
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
с учётом виртуальных функций.
а эти тут при чём?.. в смысле виртуальный деструктор, чтобы правильно работал? (не забывать его)
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
31.03.2021, 19:52
JeyCi, для тебя уровень архитектуры набора команд ЭВМ черный ящик?
многопоточность и все такое, легче воспринимается когда более менее есть представление как железка работает.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
31.03.2021, 19:52
Цитата Сообщение от JeyCi Посмотреть сообщение
а эти тут при чём?.. в смысле виртуальный деструктор, чтобы правильно работал? (не забывать его)
Притом, что если ты, например, в базовом классе запускаешь поток, который вызывает виртуальные функции этого же класса, то останавливать этот поток нужно в деструкторе наследников, а не в деструкторе базового класса.
1
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,550
31.03.2021, 20:14
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
если ты, например, в базовом классе запускаешь поток, который вызывает виртуальные функции этого же класса
однако
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ну и до кучи - у таких классов, которые запускают потоки в конструкторе или останавливают в деструкторе, не стоит делать виртуальных методов, которые могут быть вызваны в потоке. А ещё лучше, вообще помечать их final, чтоб и желания наследоваться не возникало
0
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,550
02.04.2021, 19:17
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
notify_one/all действует только если переменная стоит в wait.
да, действительно:
In particular, only threads that are waiting on the condition variable when notifyAll() is called will be signaled.
Threads that enter the wait after the notifyAll() call will wait for another signal.
сначала всех поставить в wait(), а потом сигналить с помощью notifyone()/notifyall
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
02.04.2021, 19:17

Использование boost::condition_variable
Вот пример из документации: boost::condition_variable cond; boost::mutex mut; bool data_ready; void process_data(); void...

Синхронизация потоков через condition_variable
Всем доброго времени суток! Прошу знатоков C++ помочь в решении следующего вопроса: Имеется некий циклически выполняемый поток, в...

многопоточность не работает
Здравствуйте. Пытаюсь вызвать многопоточность QVector&lt;double&gt; Perebor; //перебор значений стратегии for (double...

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

Не работает многопоточность
Добрый день. Решил заняться многопоточнстью на C#, но что-то пошло не так - она не работает. using System; using System.Threading; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
29
Ответ Создать тему
Опции темы

Новые блоги и статьи
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru