Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Объясните два случая.


Автор: DoctorSwat 7.3.2014, 11:35
Всем привет! Столкнулся с такой проблемой. Даже не проблема, а просто непонимание того, что происходит. Имею что-то вроде этого:
Код



class user_event
{
    public:

        user_event(){event_state=false;}
        user_event(bool state){event_state=state;}
        int getstate(){return event_state;}
        void setstate(bool state){event_state=state;}
        void swaps()
        {
            if(!event_state){event_state=true;}
            else{event_state=false;}
        }
        
        void wait(bool we)
        {
            for(;;){if(getstate()==we){break;}}
        }

    private:

        bool event_state;
};


user_event thread_block(false);

void re(void *p)
{
   //Do something
    thread_block.swaps();
    return 0;
}

int main()
{
   //Do something
    _beginthread(re,0,0);
    thread_block.wait(true);
    system("pause");
    return 0;
}


По задумке, после вызова wait(false), должен запуститься бесконечный цикл, который остановит главный поток, а в конце работы второго потока поменяется значение event_state и главный поток перестанет висеть, а второй прекратится. Но почему-то это не работает и главный поток прекращает свою работу сразу после создания второго.
Если вместо wait() поставить просто бесконечный цикл в потоке, а не в функции класса, то всё работает.
Кому не сложно, объясните: почему так происходит и что нужно сделать чтобы мой класс работал правильно. Заранее спасибо!  

Автор: vinter 7.3.2014, 12:02
DoctorSwat, привет.

Во-первых: так с потоками работать нельзя, ты используешь обычный bool, в который пишешь\читаешь из разных потоков, а это уже даёт неопределённый результат. Используй блокирующие механизмы или atomic.

Во-вторых: ты используешь swap в своеё функции, который выставит event_state=true и когда ты попадаешь в wait оно просто выходит, т.к. true == true.

Автор: DoctorSwat 7.3.2014, 13:03
Ну так в этом и задумка, главный поток будет блочиться, пока не поменяется значение, а оно поменяется только в конце второго потока. Про блокирующие механизмы почитаю, спасибо!

Добавлено через 14 минут и 32 секунды
Как я понял из примера с cppreference, можно использовать атомарный тип, что-то вроде этого:
Код

std::atomic<user_event> thread_block(false);

Качаю новую студию для поддержки C++11...
Спасибо за наводку!

Автор: vinter 7.3.2014, 13:27
DoctorSwat, нет, не правильно. Тебе нужно атомарное изменение event_state, именно его нужно делать атомарным. 
Посмотри мою http://scrutator.me/post/2012/08/28/parallel-world-p3.aspx, там разбирается работа с atomic. Кроме того там немного рассмотрены "гонки", которые ты имеешь сейчас.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)