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

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

24.01.2021, 16:08. Показов 4574. Ответов 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,549
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,549
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,549
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,549
31.03.2021, 20:14
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
если ты, например, в базовом классе запускаешь поток, который вызывает виртуальные функции этого же класса
однако
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ну и до кучи - у таких классов, которые запускают потоки в конструкторе или останавливают в деструкторе, не стоит делать виртуальных методов, которые могут быть вызваны в потоке. А ещё лучше, вообще помечать их final, чтоб и желания наследоваться не возникало
0
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,549
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
Ответ Создать тему
Новые блоги и статьи
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр. Дословно, отклонённая. . .
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
Очистка реквизитов и табличных частей документа при копировании (вариант 2)
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2. Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
сукцессия 43. Вторая научная статья за месяц- прайминг и гатгил
anaschu 25.07.2026
две стороны одной монеты
Более приземисто - Эстафету хвоста в .cdl (деревья эстафеты в сад).
Hrethgir 25.07.2026
В будущем, после написания блока инверсии обхода дерева (эстафеты хвоста), я планирую вернуться к нашему прошлому разговору о том, обладают ли знания целеполаганием. Тогда я пришел к выводу, что. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru