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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.67
el_gato_de_Ch
35 / 35 / 1
Регистрация: 28.04.2013
Сообщений: 110
03.06.2014, 23:06     Многопоточность, выход из бесконечного цикла c++11 #1
Всем привет. Я в задачах многопоточности - новичок (начал ей заниматься буквально несколько часов назад), инфу искал, читал, но как-то пока не помогает.

Столкнулся с задачей (с++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.
Вопрос: Как завершить цикл ?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.06.2014, 23:06     Многопоточность, выход из бесконечного цикла c++11
Посмотрите здесь:

C++ Выход из бесконечного цикла по нажатию кнопки.
Выход из цикла C++
не работает проверка бесконечного цикла C++
Выход из цикла C++
Выход из цикла C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
04.06.2014, 20:47     Многопоточность, выход из бесконечного цикла c++11 #21
Цитата Сообщение от Somebody Посмотреть сообщение
Однако всего предыдущего про оптимизацию условия и volatile это не отменяет
По-вашему, volatile даёт компилятору возможность оптимизации по отношению к _stopCycle? А добавленнии паузы в main() такой возможности лишает?

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

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

Не по теме:

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

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Somebody
2770 / 1583 / 141
Регистрация: 03.12.2007
Сообщений: 4,139
Завершенные тесты: 1
04.06.2014, 20:47     Многопоточность, выход из бесконечного цикла c++11 #22
Цитата Сообщение от alsav22 Посмотреть сообщение
По-вашему, volatile даёт компилятору возможность оптимизации по отношению к _stopCycle? А добавленнии паузы в main() такой возможности лишает?
volatile уж точно не даёт возможности оптимизации, а пауза только увеличивает до приемлемого уровня вероятность запустить второй поток раньше цикла в первом.
Что касается volatile, он заставляет заново перечитывать значение _stopCycle, и я слабо представляю в каких условиях на практике он здесь не будет работать, как задумано (наверное, это должна быть какая-то многопроцессорная система, где процессор, выполняющий второй поток не узнает вовремя об изменении _stopCycle в кэше процессора, выполняющего первый поток). В теории же, если не ошибаюсь, такой несинхронизированный доступ к не-atomic переменной - это ub.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
04.06.2014, 20:54     Многопоточность, выход из бесконечного цикла c++11 #23
Цитата Сообщение от Somebody Посмотреть сообщение
Однако всего предыдущего про оптимизацию условия и volatile это не отменяет.
Или это про код ТС? Что причина зацикливания, в его коде, может быть связана, в том числе, и с оптимизацией?
Somebody
2770 / 1583 / 141
Регистрация: 03.12.2007
Сообщений: 4,139
Завершенные тесты: 1
04.06.2014, 21:10     Многопоточность, выход из бесконечного цикла c++11 #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.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 11:23     Многопоточность, выход из бесконечного цикла c++11 #25
Цитата Сообщение от Somebody Посмотреть сообщение
Насчёт volatile - это про ошибочность использования volatile вместо std::atomic.
Утверждение об ошибочности основывается на том, что пишется по этой ссылке?
http://alenacpp.blogspot.ru/2006/04/volatile.html

Добавлено через 13 часов 30 минут
И в чём, собственно, ошибочность? Я применил volatile, чтобы исключить оптимизацию. Вы пишите:
Цитата Сообщение от Somebody Посмотреть сообщение
volatile уж точно не даёт возможности оптимизации
Значит, в этом отношении, ошибки применения нет? Насколько я понимаю, volatile и std::atomic это из разных областей, и для разного применяются.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
05.06.2014, 12:19     Многопоточность, выход из бесконечного цикла c++11 #26
Цитата Сообщение от Somebody Посмотреть сообщение
volatile уж точно не даёт возможности оптимизации, а пауза только увеличивает до приемлемого уровня вероятность запустить второй поток раньше цикла в первом.
А ничего, что пауза стоит после цикла и ни как на события до него влиять не может?

Добавлено через 8 минут
Цитата Сообщение от alsav22 Посмотреть сообщение
Значит, в этом отношении, ошибки применения нет? Насколько я понимаю, volatile и std::atomic это из разных областей, и для разного применяются.
Тебе надо не только отключить оптимизацию условия, но и гарантировать синхронизацию с первичным потоком, разделение флага между первичным и вторичным потоком, статичность/глобальность флага, то есть он должен существовать в одном и том же экземпляре для каждого экземпляра использующих его функций и фактическое существование флага в течении всего времени исполнения хотя бы одного потока. То есть флаг должен быть создан при старте первичного потока, так как он заведомо стартует первым и только после этого запускает вторичный, а освобождён при завершении того из двух потоков, который будет фактически завершён позже другого. Решает ли volatile все поставленные задачи?
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 13:01     Многопоточность, выход из бесконечного цикла c++11 #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 и мьютексы.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
05.06.2014, 13:12     Многопоточность, выход из бесконечного цикла c++11 #28
bool по идее однобитный, что уже гарантирует синхронизацию и исключает необходимость мьютексов, так как ни одна операция с отдельным битом не может быть прервана. Но по стандарту bool может быть чем угодно, лишь бы поддерживал два значения, понятные циклам с условием и условному оператору и допускал приведение к нему всего, что к нему должно приводиться, а в силу особенностей адресации фактическая разрядность кратна байту. Есть ещё такой нюанс: битовые операции в большинстве камней вообще не реализованы непосредственно, а реализуются с помощью масок, а загрузка маски в регистр - отдельная операция, тогда операция с упакованным флагом оказывается составной и может быть прервана. Но если остальные биты ни кого не интересуют, то можно выполнить операцию сразу с байтом/словом, которая уже не может быть прервана, если только не реализована через другую разрядность на RISC-камне, чья RISCковость явна и существует на логическом уровне, а не только на уровне ядра процессора.
Psilon
Master of Orion
 Аватар для Psilon
5738 / 4686 / 619
Регистрация: 10.07.2011
Сообщений: 14,160
Записей в блоге: 5
Завершенные тесты: 4
05.06.2014, 13:21     Многопоточность, выход из бесконечного цикла c++11 #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 отвечает только за отсутствие кэширования значения переменной, за его использование как средства синхронизации со ссылкой на стандарты и пр следует отрывать руки.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 13:52     Многопоточность, выход из бесконечного цикла c++11 #30
Цитата Сообщение от Psilon Посмотреть сообщение
за его использование как средства синхронизации со ссылкой на стандарты и пр
И где, здесь в теме, такое было?

Добавлено через 1 минуту
Цитата Сообщение от Psilon Посмотреть сообщение
вроде должно работать без проблем?..
Этот код, к вопросу темы, какое отношение имеет?
Psilon
Master of Orion
 Аватар для Psilon
5738 / 4686 / 619
Регистрация: 10.07.2011
Сообщений: 14,160
Записей в блоге: 5
Завершенные тесты: 4
05.06.2014, 14:00     Многопоточность, выход из бесконечного цикла c++11 #31
Цитата Сообщение от alsav22 Посмотреть сообщение
И где, здесь в теме, такое было?
Цитата Сообщение от taras atavin Посмотреть сообщение
bool по идее однобитный, что уже гарантирует синхронизацию и исключает необходимость мьютексов
далее
Этот код, к вопросу темы, какое отношение имеет?
Проблема: someThread не останавливает работу функции infinite. Цикл так и продолжает крутиться, выполняются do things и show window.
Вопрос: Как завершить цикл ?
Somebody
2770 / 1583 / 141
Регистрация: 03.12.2007
Сообщений: 4,139
Завершенные тесты: 1
05.06.2014, 14:06     Многопоточность, выход из бесконечного цикла c++11 #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 также решает и вопросы синхронизации, и в зависимости от платформы реализация может быть от простых чтения/записи до использования мьютексов.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 14:12     Многопоточность, выход из бесконечного цикла c++11 #33
Цитата Сообщение от Psilon Посмотреть сообщение
И где, здесь в теме, такое было?
Сообщение от taras atavin bool по идее однобитный, что уже гарантирует синхронизацию и исключает необходимость мьютексов
Где здесь про то, что volatile синхронизирует?
Цитата Сообщение от Psilon Посмотреть сообщение
volatile отвечает только за отсутствие кэширования значения переменной, за его использование как средства синхронизации со ссылкой на стандарты и пр следует отрывать руки.
Цитата Сообщение от Psilon Посмотреть сообщение
далее
И...? Где в вашем коде, вообще, второй поток? Как проверять будет зацикливание или нет? Этот код про то, как избежать зацикливания? Или про что?

Добавлено через 5 минут
Цитата Сообщение от Somebody Посмотреть сообщение
atomic также решает и вопросы синхронизации,
С этим никто не спорит. Но можно использовать volatile, и мьютексы для синхронизации, т.е., не заменять, в моём коде, volatile на atomic, а добавить мьютексы. Как вариант?
Psilon
Master of Orion
 Аватар для Psilon
5738 / 4686 / 619
Регистрация: 10.07.2011
Сообщений: 14,160
Записей в блоге: 5
Завершенные тесты: 4
05.06.2014, 14:22     Многопоточность, выход из бесконечного цикла c++11 #34
Цитата Сообщение от alsav22 Посмотреть сообщение
Где здесь про то, что volatile синхронизирует?
исключает необходимость мьютексов
необходимость мьютексов
мьютексов
Цитата Сообщение от alsav22 Посмотреть сообщение
И...? Где в вашем коде, вообще, второй поток? Как проверять будет зацикливание или нет? Этот код про то, как избежать зацикливания? Или про что?
главный поток - первый, создаваемый - второй. Для иллюстрации вполне достаточно. Этот код про то, что код зацикливался из-за неправильной синхронизации, а в этом коде порядок операций фиксирован.
Somebody
2770 / 1583 / 141
Регистрация: 03.12.2007
Сообщений: 4,139
Завершенные тесты: 1
05.06.2014, 14:22     Многопоточность, выход из бесконечного цикла c++11 #35
Раз тут пошёл виндовый код: в таком случае можно LONG вместо bool и InterlockedCompareExchange.
Цитата Сообщение от alsav22 Посмотреть сообщение
С этим никто не спорит. Но можно использовать volatile, и мьютексы для синхронизации, т.е., не заменять, в моём коде, volatile на atomic, а добавить мьютексы. Как вариант?
Да.
Psilon
Master of Orion
 Аватар для Psilon
5738 / 4686 / 619
Регистрация: 10.07.2011
Сообщений: 14,160
Записей в блоге: 5
Завершенные тесты: 4
05.06.2014, 14:23     Многопоточность, выход из бесконечного цикла c++11 #36
Somebody, да, про interlocked не подумал Хорошая мысль.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 14:31     Многопоточность, выход из бесконечного цикла c++11 #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;
}
Psilon
Master of Orion
 Аватар для Psilon
5738 / 4686 / 619
Регистрация: 10.07.2011
Сообщений: 14,160
Записей в блоге: 5
Завершенные тесты: 4
05.06.2014, 14:59     Многопоточность, выход из бесконечного цикла c++11 #38
alsav22, что зацикливает? 1 раз отрабатывает сообщение, после этого остановка, все как и положено.
Миниатюры
Многопоточность, выход из бесконечного цикла c++11  
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 15:03     Многопоточность, выход из бесконечного цикла c++11 #39
По-вашему, я придумываю? Вот здесь почитайте: Многопоточность, выход из бесконечного цикла c++11
Миниатюры
Многопоточность, выход из бесконечного цикла c++11  
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.06.2014, 15:17     Многопоточность, выход из бесконечного цикла c++11
Еще ссылки по теме:

Выход из бесконечного цыкла C++
Отладка бесконечного цикла C++
C++ Способы остановки бесконечного while цикла

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

Или воспользуйтесь поиском по форуму:
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 15:17     Многопоточность, выход из бесконечного цикла c++11 #40
Неправильность этого кода в том, что нет ничего, чтобы гарантировало выполнение функции inifiniteWhile() во втором потоке раньше, чем вызов функции stop() в основном потоке.
Вот здесь, во втором коде, такая гарантия сделана: Многопоточность, выход из бесконечного цикла c++11
Yandex
Объявления
05.06.2014, 15:17     Многопоточность, выход из бесконечного цикла c++11
Ответ Создать тему
Опции темы

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