Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 5.00/18: Рейтинг темы: голосов - 18, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 24.01.2021
Сообщений: 1

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

24.01.2021, 16:08. Показов 4813. Ответов 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,554
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,554
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,554
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,554
31.03.2021, 20:14
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
если ты, например, в базовом классе запускаешь поток, который вызывает виртуальные функции этого же класса
однако
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ну и до кучи - у таких классов, которые запускают потоки в конструкторе или останавливают в деструкторе, не стоит делать виртуальных методов, которые могут быть вызваны в потоке. А ещё лучше, вообще помечать их final, чтоб и желания наследоваться не возникало
0
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
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
Ответ Создать тему
Новые блоги и статьи
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru