Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.87/30: Рейтинг темы: голосов - 30, средняя оценка - 4.87
36 / 36 / 2
Регистрация: 28.04.2013
Сообщений: 110
1

Многопоточность, выход из бесконечного цикла c++11

03.06.2014, 23:06. Показов 5566. Ответов 70
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет. Я в задачах многопоточности - новичок (начал ей заниматься буквально несколько часов назад), инфу искал, читал, но как-то пока не помогает.

Столкнулся с задачей (с++11 std::thread) код не оригинальный, а упрощённый, чтобы показать саму суть, подразумевается, что все необходимые include'ы уже есть.

есть
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class SomeClass
{
private:
   bool _stopCycle;
public:
  void inifiniteWhile()
  {
      _stopCycle = false;
 
      while(!_stopCycle)
      {
          // do things ...
          // show window
      }
  }
 
   void stop() {_stopCycle = false;}
 
};
Main function

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
   SomeClass obj;
   thread someThread(&SomeClass::obj, infiniteCycle);
 
   while(/*read command from cmd*/)
   {
      if(cmd == exit)
      {
         obj.stop();
         break;
      }
   }
 
   system("pause");
}
Гарантируется, что из while(read cmd) программа выходит, т.е. я прихожу к system("pause");

Проблема: someThread не останавливает работу функции infinite. Цикл так и продолжает крутиться, выполняются do things и show window.
Вопрос: Как завершить цикл ?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
03.06.2014, 23:06
Ответы с готовыми решениями:

Выход из бесконечного цикла
Реально ли сделать выход из цикла без команды ввода? Допустим идет бесконечный цикл и в любой...

Выход из бесконечного цикла по нажатию кнопки.
Привет всем. как можно выйти из такого цикла по нажатию какой любой кнопки (например Esc) int...

Выход из бесконечного цикла
Помогите, пожалуйста, нужно выполнять цикл до тех пор, пока в консоли ничего не введут(то есть...

Выход из бесконечного цикла
Сегодня как дурачок создаю сотую тему, но все же прошу помощи. Есть программа, которая решает вот...

70
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
04.06.2014, 20:47 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Somebody Посмотреть сообщение
Однако всего предыдущего про оптимизацию условия и volatile это не отменяет
По-вашему, volatile даёт компилятору возможность оптимизации по отношению к _stopCycle? А добавленнии паузы в main() такой возможности лишает?

Добавлено через 2 минуты
Цитата Сообщение от Somebody Посмотреть сообщение
Но зацикливается не всегда, а как повезёт
С этим трудно спорить. Многопоточность, и одной ОС ведомо, как она распределит ресурс между потоками.

Добавлено через 36 минут

Не по теме:

Цитата Сообщение от Somebody Посмотреть сообщение
Такое использование volatile не соответствует стандарту. http://alenacpp.blogspot.ru/2006/04/volatile.html
А где там написано про несоответствие стандарту?

0
2835 / 1644 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
04.06.2014, 20:47 22
Цитата Сообщение от alsav22 Посмотреть сообщение
По-вашему, volatile даёт компилятору возможность оптимизации по отношению к _stopCycle? А добавленнии паузы в main() такой возможности лишает?
volatile уж точно не даёт возможности оптимизации, а пауза только увеличивает до приемлемого уровня вероятность запустить второй поток раньше цикла в первом.
Что касается volatile, он заставляет заново перечитывать значение _stopCycle, и я слабо представляю в каких условиях на практике он здесь не будет работать, как задумано (наверное, это должна быть какая-то многопроцессорная система, где процессор, выполняющий второй поток не узнает вовремя об изменении _stopCycle в кэше процессора, выполняющего первый поток). В теории же, если не ошибаюсь, такой несинхронизированный доступ к не-atomic переменной - это ub.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
04.06.2014, 20:54 23
Цитата Сообщение от Somebody Посмотреть сообщение
Однако всего предыдущего про оптимизацию условия и volatile это не отменяет.
Или это про код ТС? Что причина зацикливания, в его коде, может быть связана, в том числе, и с оптимизацией?
0
2835 / 1644 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
04.06.2014, 21:10 24
Цитата Сообщение от alsav22 Посмотреть сообщение
А где там написано про несоответствие стандарту?
Ну, там просто написано, что так не делают. Что касается стандарта, это в C++11, 1.10.0.21:
The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other. Any such data race results in undefined behavior.
В данном примере я не вижу каких-либо причин, устанавливающих отношение happens before между записью и чтением _stopCycle.

Добавлено через 3 минуты
Цитата Сообщение от alsav22 Посмотреть сообщение
Или это про код ТС? Что причина зацикливания, в его коде, может быть связана, в том числе, и с оптимизацией?
Насчёт оптимизации условия - да, это про зацикливание в коде ТС. Насчёт volatile - это про ошибочность использования volatile вместо std::atomic.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 11:23 25
Цитата Сообщение от Somebody Посмотреть сообщение
Насчёт volatile - это про ошибочность использования volatile вместо std::atomic.
Утверждение об ошибочности основывается на том, что пишется по этой ссылке?
http://alenacpp.blogspot.ru/2006/04/volatile.html

Добавлено через 13 часов 30 минут
И в чём, собственно, ошибочность? Я применил volatile, чтобы исключить оптимизацию. Вы пишите:
Цитата Сообщение от Somebody Посмотреть сообщение
volatile уж точно не даёт возможности оптимизации
Значит, в этом отношении, ошибки применения нет? Насколько я понимаю, volatile и std::atomic это из разных областей, и для разного применяются.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
05.06.2014, 12:19 26
Цитата Сообщение от Somebody Посмотреть сообщение
volatile уж точно не даёт возможности оптимизации, а пауза только увеличивает до приемлемого уровня вероятность запустить второй поток раньше цикла в первом.
А ничего, что пауза стоит после цикла и ни как на события до него влиять не может?

Добавлено через 8 минут
Цитата Сообщение от alsav22 Посмотреть сообщение
Значит, в этом отношении, ошибки применения нет? Насколько я понимаю, volatile и std::atomic это из разных областей, и для разного применяются.
Тебе надо не только отключить оптимизацию условия, но и гарантировать синхронизацию с первичным потоком, разделение флага между первичным и вторичным потоком, статичность/глобальность флага, то есть он должен существовать в одном и том же экземпляре для каждого экземпляра использующих его функций и фактическое существование флага в течении всего времени исполнения хотя бы одного потока. То есть флаг должен быть создан при старте первичного потока, так как он заведомо стартует первым и только после этого запускает вторичный, а освобождён при завершении того из двух потоков, который будет фактически завершён позже другого. Решает ли volatile все поставленные задачи?
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 13:01 27
Цитата Сообщение от taras atavin Посмотреть сообщение
А ничего, что пауза стоит после цикла и ни как на события до него влиять не может?
Разговор идёт о первом коде здесь: Многопоточность, выход из бесконечного цикла c++11
И вот об этой паузе:
C++
1
2
chrono::milliseconds dura(10);
this_thread::sleep_for(dura);
Цитата Сообщение от taras atavin Посмотреть сообщение
Тебе надо не только отключить оптимизацию условия, но и гарантировать синхронизацию
Цитата Сообщение от taras atavin Посмотреть сообщение
Решает ли volatile все поставленные задачи?
Понятно, что volatile не решает вопрос синхронизации. Но при чём здесь то, что volatile нужно заменить на atomic, как пишет Somebody? volatile для одного (для чего я его и использовал), atomic для другого. Весь вопрос сводится к тому: является ли тип bool атомарным или не является. Там, где я с этим сталкивался, писали, что является. По ссылке, которую выложил Somebody, пишут, что может и не являться. Если не является, то можно использавать volatile и мьютексы.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
05.06.2014, 13:12 28
bool по идее однобитный, что уже гарантирует синхронизацию и исключает необходимость мьютексов, так как ни одна операция с отдельным битом не может быть прервана. Но по стандарту bool может быть чем угодно, лишь бы поддерживал два значения, понятные циклам с условием и условному оператору и допускал приведение к нему всего, что к нему должно приводиться, а в силу особенностей адресации фактическая разрядность кратна байту. Есть ещё такой нюанс: битовые операции в большинстве камней вообще не реализованы непосредственно, а реализуются с помощью масок, а загрузка маски в регистр - отдельная операция, тогда операция с упакованным флагом оказывается составной и может быть прервана. Но если остальные биты ни кого не интересуют, то можно выполнить операцию сразу с байтом/словом, которая уже не может быть прервана, если только не реализована через другую разрядность на RISC-камне, чья RISCковость явна и существует на логическом уровне, а не только на уровне ядра процессора.
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
05.06.2014, 13:21 29
Ребят, я в плюсах не оч шарю, но так вроде должно работать без проблем?..
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
class SomeClass
{
    CRITICAL_SECTION gCS;
    volatile bool _stopCycle;
public:
    SomeClass()
    {
        InitializeCriticalSection(&gCS);
    }
 
    ~SomeClass()
    {
        DeleteCriticalSection(&gCS);
    }
 
    void inifiniteWhile()   {
        if (_stopCycle)
        {
            EnterCriticalSection(&gCS);
            _stopCycle = false;
            LeaveCriticalSection(&gCS);
        }
        while (!_stopCycle)
        {
            cout << "inifiniteWhile" << endl;
        }
    }
 
    void stop() {
        if (!_stopCycle)
        {
            EnterCriticalSection(&gCS);
            _stopCycle = true;
            LeaveCriticalSection(&gCS);
        }
    }
};
Добавлено через 1 минуту
taras atavin, bool как правило является int-ом из-за проблем с выравниванием памяти и прочими прелестями. В лучшем случае он однобайтный. Но однобитных булов вообще не бывает афайк.

Добавлено через 1 минуту
Цитата Сообщение от taras atavin Посмотреть сообщение
Тебе надо не только отключить оптимизацию условия, но и гарантировать синхронизацию с первичным потоком, разделение флага между первичным и вторичным потоком, статичность/глобальность флага, то есть он должен существовать в одном и том же экземпляре для каждого экземпляра использующих его функций и фактическое существование флага в течении всего времени исполнения хотя бы одного потока. То есть флаг должен быть создан при старте первичного потока, так как он заведомо стартует первым и только после этого запускает вторичный, а освобождён при завершении того из двух потоков, который будет фактически завершён позже другого. Решает ли volatile все поставленные задачи?
volatile отвечает только за отсутствие кэширования значения переменной, за его использование как средства синхронизации со ссылкой на стандарты и пр следует отрывать руки.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 13:52 30
Цитата Сообщение от Psilon Посмотреть сообщение
за его использование как средства синхронизации со ссылкой на стандарты и пр
И где, здесь в теме, такое было?

Добавлено через 1 минуту
Цитата Сообщение от Psilon Посмотреть сообщение
вроде должно работать без проблем?..
Этот код, к вопросу темы, какое отношение имеет?
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
05.06.2014, 14:00 31
Цитата Сообщение от alsav22 Посмотреть сообщение
И где, здесь в теме, такое было?
Цитата Сообщение от taras atavin Посмотреть сообщение
bool по идее однобитный, что уже гарантирует синхронизацию и исключает необходимость мьютексов
далее
Этот код, к вопросу темы, какое отношение имеет?
Проблема: someThread не останавливает работу функции infinite. Цикл так и продолжает крутиться, выполняются do things и show window.
Вопрос: Как завершить цикл ?
0
2835 / 1644 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
05.06.2014, 14:06 32
Цитата Сообщение от alsav22 Посмотреть сообщение
Значит, в этом отношении, ошибки применения нет? Насколько я понимаю, volatile и std::atomic это из разных областей, и для разного применяются.
В этом отношении ошибки нет. Но volatile изначально был введён для работы с отображёнными на память устройствами ввода-вывода. C++98 ничего не говорил о многопоточности, так что volatile был лучше, чем ничего; к тому же MS в своих компиляторах наделил его дополнительным смыслом (acquire/release semantics), которого нет в стандарте. В C++11 решили ничего нового для volatile не придумывать, и просто добавили atomic типы.
Цитата Сообщение от alsav22 Посмотреть сообщение
Понятно, что volatile не решает вопрос синхронизации. Но при чём здесь то, что volatile нужно заменить на atomic, как пишет Somebody? volatile для одного (для чего я его и использовал), atomic для другого. Весь вопрос сводится к тому: является ли тип bool атомарным или не является.
atomic также решает и вопросы синхронизации, и в зависимости от платформы реализация может быть от простых чтения/записи до использования мьютексов.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 14:12 33
Цитата Сообщение от Psilon Посмотреть сообщение
И где, здесь в теме, такое было?
Сообщение от taras atavin bool по идее однобитный, что уже гарантирует синхронизацию и исключает необходимость мьютексов
Где здесь про то, что volatile синхронизирует?
Цитата Сообщение от Psilon Посмотреть сообщение
volatile отвечает только за отсутствие кэширования значения переменной, за его использование как средства синхронизации со ссылкой на стандарты и пр следует отрывать руки.
Цитата Сообщение от Psilon Посмотреть сообщение
далее
И...? Где в вашем коде, вообще, второй поток? Как проверять будет зацикливание или нет? Этот код про то, как избежать зацикливания? Или про что?

Добавлено через 5 минут
Цитата Сообщение от Somebody Посмотреть сообщение
atomic также решает и вопросы синхронизации,
С этим никто не спорит. Но можно использовать volatile, и мьютексы для синхронизации, т.е., не заменять, в моём коде, volatile на atomic, а добавить мьютексы. Как вариант?
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
05.06.2014, 14:22 34
Цитата Сообщение от alsav22 Посмотреть сообщение
Где здесь про то, что volatile синхронизирует?
исключает необходимость мьютексов
необходимость мьютексов
мьютексов
Цитата Сообщение от alsav22 Посмотреть сообщение
И...? Где в вашем коде, вообще, второй поток? Как проверять будет зацикливание или нет? Этот код про то, как избежать зацикливания? Или про что?
главный поток - первый, создаваемый - второй. Для иллюстрации вполне достаточно. Этот код про то, что код зацикливался из-за неправильной синхронизации, а в этом коде порядок операций фиксирован.
0
2835 / 1644 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
05.06.2014, 14:22 35
Раз тут пошёл виндовый код: в таком случае можно LONG вместо bool и InterlockedCompareExchange.
Цитата Сообщение от alsav22 Посмотреть сообщение
С этим никто не спорит. Но можно использовать volatile, и мьютексы для синхронизации, т.е., не заменять, в моём коде, volatile на atomic, а добавить мьютексы. Как вариант?
Да.
1
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
05.06.2014, 14:23 36
Somebody, да, про interlocked не подумал Хорошая мысль.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 14:31 37
Цитата Сообщение от Psilon Посмотреть сообщение
исключает необходимость мьютексов
bool и volatile, по-вашему, это одинаковые слова?
Цитата Сообщение от Psilon Посмотреть сообщение
главный поток - первый, создаваемый - второй.
Где они в вашем коде?
Цитата Сообщение от Psilon Посмотреть сообщение
Этот код про то, что код зацикливался из-за неправильной синхронизации,
Код зацикливается совсем по другой причине (так же как и ваш, если не добавить паузу перед циклом в основном потоке).

Добавлено через 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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <thread>
#include <mutex>
#include <cstdlib>
#include <Windows.h>
using namespace std;
 
 
class SomeClass
{
    CRITICAL_SECTION gCS;
    volatile bool _stopCycle;
public:
    SomeClass()
    {
        InitializeCriticalSection(&gCS);
    }
 
    ~SomeClass()
    {
        DeleteCriticalSection(&gCS);
    }
 
    void inifiniteWhile()   {
        if (_stopCycle)
        {
            EnterCriticalSection(&gCS);
            _stopCycle = false;
            LeaveCriticalSection(&gCS);
        }
        while (!_stopCycle)
        {
            cout << "inifiniteWhile" << endl;
        }
    }
 
    void stop() {
        if (!_stopCycle)
        {
            EnterCriticalSection(&gCS);
            _stopCycle = true;
            LeaveCriticalSection(&gCS);
        }
    }
};
 
int main(int argv, char* argc[])
{
    SomeClass obj;
    thread someThread(&SomeClass::inifiniteWhile, &obj);
    someThread.detach();
 
    while(true)
    {
        if(true)
        {
            obj.stop();
            break;
        }
    }
 
    system("pause");
    
    return 0;
}
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
05.06.2014, 14:59 38
alsav22, что зацикливает? 1 раз отрабатывает сообщение, после этого остановка, все как и положено.
Миниатюры
Многопоточность, выход из бесконечного цикла c++11  
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 15:03 39
По-вашему, я придумываю? Вот здесь почитайте: Многопоточность, выход из бесконечного цикла c++11
Миниатюры
Многопоточность, выход из бесконечного цикла c++11  
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 15:17 40
Неправильность этого кода в том, что нет ничего, чтобы гарантировало выполнение функции inifiniteWhile() во втором потоке раньше, чем вызов функции stop() в основном потоке.
Вот здесь, во втором коде, такая гарантия сделана: Многопоточность, выход из бесконечного цикла c++11
1
05.06.2014, 15:17
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.06.2014, 15:17
Помогаю со студенческими работами здесь

Выход из бесконечного цикла
я начинаю изучать PHP, задача такая: есть бесконечный цикл отправки POST запроса как сделать чтоб ...

Выход из бесконечного цикла
Здравствуйте Посмотрите вот такой интересный код s := 1; i := 1; repeat s := s/2; ...

Выход из бесконечного цикла
Как выйти из этого цикла при условии, что сгенерируется значение FAFZYMA2 while(true) ...

Выход из бесконечного цикла программно
Всем привет! Хочу сделать прогу дни рождения. Так вот вопрос такой подскажите как выходить из...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru