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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
NeonLost
Пес войны
74 / 85 / 3
Регистрация: 23.02.2012
Сообщений: 653
#1

Deadlock и racecondition проверить код - C++

21.07.2014, 07:40. Просмотров 517. Ответов 8
Метки нет (Все метки)

класс принимает функцию и количество потоков...и все время поддерживает одновременное выполнение 10 потоков этой функции...интересуют ошибки связанные с многопоточным программированием...может еще подскажите как лучше сделать?..)

заголовочный файл
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class gthread
{
    typedef void (*pFunc) ();
public:
    gthread(pFunc func, unsigned short int, unsigned short int);
    ~gthread();
    void start();
    void stop();
private:
    pFunc _func;
    std::mutex _mut;
    unsigned short int _threadCounter;
    unsigned short int _threadNumber;
    unsigned short int _breakTime; //milliseconds
    bool _condition;
    void invoker();
    void abuse();
};
срр файл
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
void gthread::invoker()
{
    (_func)();
}
 
gthread::gthread(pFunc func, unsigned short int threadNumber, unsigned short int breakTime = 100 )
{
    _func= func;
    _threadNumber = threadNumber;
    _threadCounter = 0;
    _breakTime = breakTime;
    _condition = true;
}
 
gthread::~gthread()
{
}
 
void gthread::start()
{
    std::thread abuser(&gthread::abuse, this);
    abuser.detach();
}
 
void gthread::abuse()
{
    while(_condition)
    {
        while(_threadCounter<_threadNumber) 
        {
            std::async([this]
            {
                _mut.lock();
                _threadCounter++;
                _mut.unlock();
                std::thread t(&gthread::invoker, this);
                t.join();
                _mut.lock();
                _threadCounter--;
                _mut.unlock();
            });
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(_breakTime));
    }
}
 
void gthread::stop()
{
    _condition = false;
}
тест
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void StartThread()
{
    //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        cout<<std::this_thread::get_id()<<endl;
}
 
int main()
{
    gthread q(&StartThread, 10);
    q.start();
    std::this_thread::sleep_for(std::chrono::seconds(100));
    q.stop();
    getchar();
    return 0;
}
Добавлено через 6 часов 55 минут
особенно интересны строки 30-40...)
так вроде все работает...)

Добавлено через 10 часов 39 минут
ну хоть кто-нибудь...)
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.07.2014, 07:40     Deadlock и racecondition проверить код
Посмотрите здесь:

C++ Проверить код на корректность
C++ Проверить код
Чем можно проверить код С++? C++
Проверить код на правильность C++
C++ Проверить код
C++ Проверить код
C++ Проверить код
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ilot
Модератор
Эксперт С++
1785 / 1160 / 225
Регистрация: 16.05.2013
Сообщений: 3,056
Записей в блоге: 5
Завершенные тесты: 1
21.07.2014, 08:53     Deadlock и racecondition проверить код #2
Цитата Сообщение от NeonLost Посмотреть сообщение
особенно интересны строки 30-40...)
Верное замечание. Не рекомендуется вызывать непосредственно функции lock и unlock свойства мьютекса. Используйте std::lock_guard. Хотя возможно в данном случае проще воспользоваться атомарным инкрементом и _threadCounter сделать атомарным типом?
Еще в конструкторе список инициализации уже не приемлим?
aLarman
641 / 562 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
21.07.2014, 09:39     Deadlock и racecondition проверить код #3
Цитата Сообщение от NeonLost Посмотреть сообщение
может еще подскажите как лучше сделать?..)
посмотреть в сторону пула потоков
NeonLost
Пес войны
74 / 85 / 3
Регистрация: 23.02.2012
Сообщений: 653
21.07.2014, 21:00  [ТС]     Deadlock и racecondition проверить код #4
Верное замечание. Не рекомендуется вызывать непосредственно функции lock и unlock свойства мьютекса. Используйте std::lock_guard. Хотя возможно в данном случае проще воспользоваться атомарным инкрементом и _threadCounter сделать атомарным типом?
Еще в конструкторе список инициализации уже не приемлим?
std::lock_guard тут не подойдет, если его поставить в самом начале функции, то он разлочит, когда она завершится...а на счет атомарности вы правы, спасибо...)
я не помню как сделать в списке инициаллизации значение по умолчанию...(

посмотреть в сторону пула потоков
возможно это верное решение...но я не уверен, что, например, росо::threadpool умеет выполнять такую задачу, хотя честно признаюсь ни разу не использовал...)

Добавлено через 9 минут
Цитата Сообщение от Ilot Посмотреть сообщение
Верное замечание. Не рекомендуется вызывать непосредственно функции lock и unlock свойства мьютекса. Используйте std::lock_guard. Хотя возможно в данном случае проще воспользоваться атомарным инкрементом и _threadCounter сделать атомарным типом?
Еще в конструкторе список инициализации уже не приемлим?
на самом деле я немного изменил код, чтоб быть точно уверенным, что поток запустится сразу после выполнения предыдущего, а не спустя какое-то время и не гоняя в холостую процессор...и надобность в этом мьютексе сразу отпала
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void gthread::abuse()
{
    while(_threadCounter<_threadNumber) 
    {
        _threadCounter++;
        std::async([this]
        {
            while(_condition)
            {
                std::thread t(&gthread::invoker, this);
                t.join();
            }
        });
    }
}
все же интересно на сколько это работает, и на сколько это велосипед...)
особенно интересно, нужно ли делать атомарной переменную _condition и что будет, если я из меин потока поменяю ее значение...)
Убежденный
Системный программист
Эксперт С++
15101 / 6796 / 1073
Регистрация: 02.05.2013
Сообщений: 11,108
Завершенные тесты: 1
21.07.2014, 22:32     Deadlock и racecondition проверить код #5
Цитата Сообщение от NeonLost Посмотреть сообщение
while(_condition)
Может крутиться вечно.
Типа такого:
Assembler
1
2
3
4
5
6
mov eax, dword ptr[_condition]
 
@loop:
cmp eax, 0
...
jmp @loop
aLarman
641 / 562 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
21.07.2014, 22:33     Deadlock и racecondition проверить код #6
Цитата Сообщение от NeonLost Посмотреть сообщение
росо::threadpool умеет выполнять такую задачу
в лбюбой книге по параллельному программированию рассказано как сделать пул самому, там нужна очередь с мьютексами и несколько потоков, и все
NeonLost
Пес войны
74 / 85 / 3
Регистрация: 23.02.2012
Сообщений: 653
21.07.2014, 22:47  [ТС]     Deadlock и racecondition проверить код #7
Может крутиться вечно.
Типа такого:
Код ASM

mov eax, dword ptr[_condition]

@loop:
cmp eax, 0
...
jmp @loop
получается при определенных настройках оптимизатора, может не прокатить?..(
_condition поместить в кучу, а не в стек, то спасет?..)
Убежденный
Системный программист
Эксперт С++
15101 / 6796 / 1073
Регистрация: 02.05.2013
Сообщений: 11,108
Завершенные тесты: 1
21.07.2014, 22:51     Deadlock и racecondition проверить код #8
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от NeonLost Посмотреть сообщение
_condition поместить в кучу, а не в стек, то спасет?..)
Без разницы.
С _condition нужно обращаться специальным образом.
Например, в Visual C++ ее достаточно сделать volatile, это заставит
компилятор каждый раз при обращении программы к переменной
перечитывать ее из памяти.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.07.2014, 20:04     Deadlock и racecondition проверить код
Еще ссылки по теме:

C++ проверить код на с++
Проверить скомпилируется ли код C++
Проверить код C++
Проверить код на правильность C++
Проверить верен ли код. CodeBlock C++

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

Или воспользуйтесь поиском по форуму:
NeonLost
Пес войны
74 / 85 / 3
Регистрация: 23.02.2012
Сообщений: 653
22.07.2014, 20:04  [ТС]     Deadlock и racecondition проверить код #9
Без разницы.
С _condition нужно обращаться специальным образом.
Например, в Visual C++ ее достаточно сделать volatile, это заставит
компилятор каждый раз при обращении программы к переменной
перечитывать ее из памяти.
спасибо большое...сразу не подумал бы...)

Добавлено через 1 минуту
а еще у меня цитаты не взлетают почему-то...(

Добавлено через 11 минут
если кому-то интересно про volatile, то алена c++ неплохо показала пример, один в один как у меня...)
Компилятор скорее всего оптимизирует код вроде такого, если переменная cancel не менялась в теле цикла.


bool cancel = false;
while( !cancel ) {
;
}

Если cancel не меняется, то ее и проверять каждый раз незачем, компилятор и не будет ее проверять.

Зато если вы укажете перед переменной volatile, то оптимизиации не будет. Предполагается, что переменная cancel могла измениться каким-то волшебным образом.

volatile bool cancel = false;
while( !cancel ) {
;
}
Добавлено через 6 минут
еще довольно важный момент, который я проморгал
C++
1
2
3
4
5
6
7
8
std::async(std::launch::async, [this]
        {
            while(_condition)
            {
                std::thread t(&gthread::invoker, this);
                t.join();
            }
        });
если std::async в параметрах не указать std::launch::async, то она будет запускать потоки на свое усмотрение(некоторые с lazy init)

Добавлено через 24 минуты
пока класс находится в таком состоянии...интересны еще мнения...)

заголовок
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
#include <thread>
#include <future>
 
class gthread
{
    typedef void        (*pFunc) ();
 
public:
    gthread(pFunc func, unsigned short int threadNumber): 
    _func               (func), 
    _threadNumber       (threadNumber),
    _threadCounter      (0),
    _breakTime          (breakTime),
    _condition          (true)  {}
    void start();
    void stop();
 
private:
    pFunc               _func;
    unsigned short int  _threadCounter;
    unsigned short int  _threadNumber;
    volatile bool       _condition;
    void invoker();
    void abuse();
};
код
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 "gthread.h"
 
void gthread::start()
{
    std::thread abuser(&gthread::abuse, this);
    abuser.detach();
}
 
void gthread::stop()
{
    _condition = false;
}
 
void gthread::invoker()
{
    (_func)();
}
 
 
void gthread::abuse()
{
    while(_threadCounter<_threadNumber) 
    {
        _threadCounter++;
        std::async(std::launch::async, [this]
        {
            while(_condition)
            {
                std::thread t(&gthread::invoker, this);
                t.join();
            }
        });
    }
}
Добавлено через 20 часов 15 минут
ап...)
Yandex
Объявления
22.07.2014, 20:04     Deadlock и racecondition проверить код
Ответ Создать тему
Опции темы

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