Форум программистов, компьютерный форум CyberForum.ru

Некорректная работа условных переменных в приведенном коде - C++

Восстановить пароль Регистрация
 
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 467
Завершенные тесты: 1
31.01.2014, 00:24     Некорректная работа условных переменных в приведенном коде #1
хай всем!)начал недавно изучать многопоточность,а именно работу с ней с помощью стандартной библиотеки C++.Дошел до условных переменных, и сразу же решил написать маленький примерчик, чтобы все это закрепить как говорится)Но тут же столкнулся с проблемой...
Короче вот то что я придумал: Есть два потока(один из них является главным потоком main()).Второй поток,после его запуска начинает рандомно получать числа 0 или 1 и отправлять главному потоку сигнал о получении числа.В главном потоке с помощью условных переменных стоит условие,что если второй поток срандомил число 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
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
 
mutex m;
condition_variable var;
int n;
 
void threadfun()
{
while(true)
{
unique_lock<mutex> lock(m);
n = rand() % 2;
cout << n;
var.notify_one();
lock.unlock();
}
}
 
void main()
{
thread th(threadfun);
th.detach();
while(true)
{
unique_lock<mutex> lock(m);
var.wait(lock,[] {if(n == 1) return true; else return false;});
cout<< "a";
lock.unlock();
}
}
Результат кода должен быть:
001а1а01а1а1а00...
То есть если есть 1,то за ней сразу 'а'
А у меня почему то вот тпк выводит:
1а1а001а11а01а1а000111а001а...
То есть иногда пропускается 1,а из этого следует что сигнал о поступившем числе не правильно передается в главный поток.И еще...зачем вообще мьютекс нужен в условных переменных?я читаю книгу и не понимаю зачем они его там используют,я сделал по аналогии
Помогите разобраться пожалуйста!желательно с объяснениями
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.01.2014, 00:24     Некорректная работа условных переменных в приведенном коде
Посмотрите здесь:

C++ Исправить ошибки в приведенном коде
C++ Найти и исправить ошибки в приведенном коде
C++ Не работает сортировка в приведенном коде
Найти ошибку в приведенном коде C++
Найти ошибку в приведенном коде C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
31.01.2014, 01:01     Некорректная работа условных переменных в приведенном коде #2
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
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
 
std::mutex m;
std::condition_variable var;
int n = 0;
 
void threadfun()
{
   while(true)
   {
      std::unique_lock<std::mutex> lock(m);
      n = rand() % 2;
      std::cout << n;
      lock.unlock();
      var.notify_one();
      std::this_thread::sleep_for(std::chrono::seconds(1));
   }
}
 
int main()
{
   std::srand(static_cast<unsigned>(time(nullptr)));
 
   std::thread th(threadfun);
   th.detach();
 
   while(true)
   {
      std::unique_lock<std::mutex> lock(m);
      var.wait(lock, [] { if(n == 1) return true; else return false; });
      std::cout << " - a\n";
      n = 0;
      lock.unlock();
   }
 
   std::cout << "\nDone." << std::endl;
   return 0;
}
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 467
Завершенные тесты: 1
31.01.2014, 01:58  [ТС]     Некорректная работа условных переменных в приведенном коде #3
ничегл не понял,что вы написали.
зачем тут
C++
1
std::this_thread::sleep_for(std::chrono::seconds(1));
и вот это
C++
1
std::srand(static_cast<unsigned>(time(nullptr)));
что это вообще такое?
И зачем нужны мьютексы в условных операциях.И можете сказать почему мой код не работает
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
31.01.2014, 12:15     Некорректная работа условных переменных в приведенном коде #4
Цитата Сообщение от Bretbas Посмотреть сообщение
зачем тут
std::this_thread::sleep_for(std::chrono::seconds(1));
Для того что бы успеть увидеть что на консоль выводится, а то у тебе в коде в циклах все с огромной скоростью выводится.
Цитата Сообщение от Bretbas Посмотреть сообщение
и вот это
std::srand(static_cast<unsigned>(time(nullptr)));
Фактически, тоже самое что и srand(time(0)) - в любой книге для начинающих про это пишут. Можешь не использовать - здесь не обязательно.
Цитата Сообщение от Bretbas Посмотреть сообщение
И зачем нужны мьютексы в условных операциях
Функция wait принимает в своем первом аргументе std::unique_lock<std::mutex>& : std::condition_variable::wait - без мютекса никак не обойтись - это тоже должно должно было объясняться в книге.
В общем, в твоем коде нет синхронизации вывода на консоль, - скорее всего wait не успевает захватить мютекс. А в то время второй цикл в функции threadfun его успешно захватывает, меняет переменную n и выводит не то что ожидалось. Вот как раз задержка тут и помогает.

Добавлено через 5 минут
Вот результат работы моего кода:
1a1a001a000001a1a1a1a1a1a1a01a01a001a001a001a1a01a01a01a1a1a01a1a01a1a01a1a
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 467
Завершенные тесты: 1
31.01.2014, 21:57  [ТС]     Некорректная работа условных переменных в приведенном коде #5
в книге не написано зачем нужны именно мьютексы в условных переменных,просто там использованы примеры где они точно нужны для разделения общих данных между потоками.В примере,который я написал с "001а1а0..." мьютексы тоже необходимы,т.к нужно на одном и том же экране выводить результат двух потоков,то есть имеются разделяемые данные.
А к примеру в других задачах,где необходимы условные переменные,но не нужны мьютексы как быть?
К примеру задача с которой я столкнулся недавно:
Есть 3 потока(один из них главный).В главном потоке я завожу второй поток и жду его завершения.Второй поток имеет в своем теле цикл передвижения фигуры.Причем перед выполнения этого цикла заводится еще один поток,который отслеживает нажатие клавиши -вверх,вниз,влево,вправо,escape.Суть в том,что мне нужно по нажатию на escape завершить третий поток(отслеживание нажатие),завершить второй поток ДОСРОЧНО,то есть не дождаться завершения цикла передвижения фигуры.И следовательно вернуться в третий главный поток.
Фуххх...)Вроде все рассказал)Суть в том,что я пока что использую winapi и завершаю досрочно второй поток с помощью функции TerminateThread(HANDLE).Но я знаю,что эту функцию не рекомендуется использовать,поэтому я решил перейти на стандартную библиотеку C++ и использовать условные переменные в данном случае.То есть по нажатию на кнопку escape,третий поток должен послать сигнал во второй поток,чтобы тот в свою очередь завершился и отдал управление в третий главный поток.Вот как то так нужно наверное сделать.
А теперь собственно вопросы:
1.Как реализовать такую систему потоков?
2.Зачем здесь мьютексы,если здесь нет разделяемых данных?
3.Может здесь вовсе не нужны условные переменные,и можно реализовать данную систему как-то подругому?
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 467
Завершенные тесты: 1
02.02.2014, 01:09  [ТС]     Некорректная работа условных переменных в приведенном коде #6
Ну что,кто нибудь поможет?
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 467
Завершенные тесты: 1
03.02.2014, 01:13  [ТС]     Некорректная работа условных переменных в приведенном коде #7
есть тут кто?
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 467
Завершенные тесты: 1
06.02.2014, 00:57  [ТС]     Некорректная работа условных переменных в приведенном коде #8
ну так че,кто нибудь поможет?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.02.2014, 02:30     Некорректная работа условных переменных в приведенном коде
Еще ссылки по теме:

C++ Не правильно работает if в приведенном коде
Найти ошибку в приведенном коде C++
Найти ошибку в приведенном коде C++

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

Или воспользуйтесь поиском по форуму:
DrOffset
6423 / 3797 / 878
Регистрация: 30.01.2014
Сообщений: 6,588
06.02.2014, 02:30     Некорректная работа условных переменных в приведенном коде #9
Цитата Сообщение от Bretbas Посмотреть сообщение
3.Может здесь вовсе не нужны условные переменные,и можно реализовать данную систему как-то подругому?
Назначение std::condition_variable ожидать изменения некоего состояния. Он не спроектирован для того, чтобы быть просто получателем некоторого сообщения. Ты можешь использовать его, например, когда поток потребитель должен ожидать, пока в очереди появятся сообщения:
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
Event get_from_queue()
{
    std::unique_lock l(queue_mutex);
    while(event_queue.empty())
    {
        queue_condition.wait(l);
    }
    Event event = event_queue.top();
    event_queue.pop();
    return event;
}
 
void thread()
{
    while(true)
    {
        Event e = get_from_queue();
 
        //обработка события выхода
        if(e->type() == Event::ThreadExit)
        {
            break;
        }
        //обработка остальных событий
        process_event(e);
    }
}
В твоем случае, когда нужно послать потоку выполняющему длительную операцию сигнал о завершении, естественно нельзя использовать terminate, потому что ты потеряешь всю память, которая была у потока и деструкторы объектов внутри потока не будут вызваны. Самый просто способ решить проблему, это завести булевскую переменную, защитить ее изменение мьютексом, в цикле передвижения фигуры вставить проверку этой переменной (естественно тоже с мьютексом), если переменная true, то выйти из цикла. Если операция очень длительная, можно разбить ее на условные подоперации и проверять такую переменную в каждой из них.
Yandex
Объявления
06.02.2014, 02:30     Некорректная работа условных переменных в приведенном коде
Ответ Создать тему
Опции темы

Текущее время: 17:30. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru