Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

C++ параллельные потоки

590
05 мая 2010 года
Gigahard
223 / / 03.04.2006
Есть некий класс, который при создании экземпляра объекта, создает отдельный рабочий поток.

Для того, чтобы реализовать процедуру потока в качестве члена класса, нужно создать статическую функцию обработчик, которая в свою очередь уже будет запускать индивидуальную функцию обработки для каждого из созданных объектов класса.

Меня смущает момент доступа нескольких объектов к статической функции, из параллельных потоков. Не может ли тут возникнуть конфликта? Что нужно предпринять, во избежании?
11
05 мая 2010 года
oxotnik333
2.9K / / 03.08.2007
Конфликт может возникнуть если одновременно к одним и тем же данным будет доступ. Если в ф-ции будут использоваться локальные переменные, то при каждом вызове они будут создаваться свои и это не помешает.
590
05 мая 2010 года
Gigahard
223 / / 03.04.2006
Цитата: oxotnik333
Конфликт может возникнуть если одновременно к одним и тем же данным будет доступ. Если в ф-ции будут использоваться локальные переменные, то при каждом вызове они будут создаваться свои и это не помешает.



Дело в том, что в статическую функцию мы уже передаем данные, а именно указатель на объект, который в статической функции запускает свой локальный метод.

Что то типа

Код:
class Test
{
    public:
        Test(unsigned char inObjId):mThrHandle(NULL), mObjId(inObjId){}
        ~Test()
        {
         //...
        }

        // Активация потока
    bool start()
        {
                mThrHandle=CreateThread(NULL,
                            NULL,
                                        _threadstart, //Статический "запускальщик" функции обработки потока
                                        this, //Параметр статической функции, указатель на объект
                                        NULL,
                                        NULL);
            return true;
        }

        unsigned char mObjId; //Идентификатор объекта

        protected:
        HANDLE mThrHandle;

        static __stdcall DWORD _threadstart(void* param)
        {
            static_cast<Test*>(param)->[color="green"]myFunc()[/color]; [color="red"]//Вот не будет ли искажаться переменная param при одновременном обращении нескольких объектов из разных потоков?[/color]
                return 0;
        }

        //Метод объекта
        void [color="green"]myFunc()[/color]
        {
                for(;;)
                {
                cout << mObjId << endl; //Выводим ID объекта
                        Sleep(1000);
                }
        }

};


Ведь в случае статической функции, все ее переменные для всех экземпляров класса будут общими? В т.ч. и параметры?

______________________
Кажется я туплю... _threadstart будет запускаться ведь последовательно из одного потока... Т.е. поочередно и безконфликтно... ?
5
05 мая 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Gigahard
Ведь в случае статической функции, все ее переменные для всех экземпляров класса будут общими? В т.ч. и параметры?


Параметры передаются через стек/регистры. У каждого потока свой стек и регистры.
Они будут одинаковыми если их задать таковыми.

11
05 мая 2010 года
oxotnik333
2.9K / / 03.08.2007
Каждый экземпляр класса Test запускает один поток, т.о. при создании нового экземпляра этого класса все его члены будут создаваться новые (кроме статических), в т.ч. и [COLOR=Black]myFunc(). В общем ничего страшного не произойдет.
[/COLOR]
590
05 мая 2010 года
Gigahard
223 / / 03.04.2006
Меня просто проглючило... У меня потоки работают с циклами, так я чего то с начала ступил, с чего то вдруг взял, что статическая функция тоже в разных потоках циклически вызываться будет. :)
Потом посмотрел, да она ж в основном потоке только один раз для каждого объекта вызывается, да итого последовательно, а значит безконфликтно.
В общем, опасаться стоит только в случае обращения к статическим членам класса или к глобальным данным из разных потоков, а так вроде все нормалек получается :)
590
11 мая 2010 года
Gigahard
223 / / 03.04.2006
Кстати, такой вот вопрос...Допустим объект класса создается в основном потоке программы. После этого, объект создает отдельный поток с вычислениями. В том потоке, он обращается к другим методам объекта.
Вот возник вопрос, если объект создан в основном потоке, а обращение к его методам идет из дополнительного потока, то это как межпотоковый обмен получается? Или методы объекта запускаясь в дополнительном потоке изолированы от основного?
602
12 мая 2010 года
KPI Student
265 / / 16.12.2006
Методы объекта - это код. Они существуют в единственном экземпляре, как их скомпилировал компилятор. Адресное пространство процесса одно и абсолютно одинаково доступно всем его потокам.

Поток в виндовс - это "единичка исполнения", независимый "конвейер" команд, кидающий их процессору со своим личным контекстом.

Контекст - это системная информация о процесе, в ней хранится указатель на код, который поток сейчас выполняет, его стек (очень упростил) и регистры. Это личная информация потока. Все остальное - общее.

Вот пример:
 
Код:
...

int a=1;

void f(int* i)    { int b=0; ++(*i); }
void g(int  k)    { int b=0; ++k; }

thread1.start( f, &a ); // поток запустится и вызовет f(&a);
thread2.start( f, &a );
thread3.start( g, a );


В результате выполнения такго кода создается 2 потока, все два параллельно бегут-бегут-бегут-бегут и забегают в одну и ту же функцию f(int* ), которая получает указатель на расположенную в памяти процесса переменную а. Так как адресное пространство общее, то каждый поток будет увеличивать на 1 одну и ту же ячейку общего адресного пространства. Вероятно, после выполнения такого кода значение переменной а будет увеличено два раза.

Внутри одной и той же функции f один и тот же код в двух потоках создает локальную переменную b. Она создается в стеке. Стек (очень приблженно) для каждого потока свой, индивидуальный. Соответственно, переменная b для каждого потока будет своя.

Третий поток принимает целое "по значению", то есть сздает свою локальную копию передаваемых ему данных. В стеке. И меняет свою личную копию, не оказывая влияния на общие данные.

Цитата:
Вероятно, после выполнения такого кода значение переменной а будет увеличено два раза.

Если для вашей задачи формулировка "этот код в зависимости от случайных обстоятельств может увеличить значение переменной на 2, а может и не увеличить его на 2, или увеличить, но не на два..." недопустима (например, не устраивает заказчика системы наведения ракет на луну), то следует задуматься о синхронизации между потоками при обращении к общим данным, чтобы ничего не повредить.

590
12 мая 2010 года
Gigahard
223 / / 03.04.2006
Вот набросок кода...

Код:
class Test
{
    Test(): mVar(0)
    void write()
    {
        //что то периодически пишем в mVar
    }
    unsigned int read()
    {
        //что то периодически читаем из mVar
    }
    protected:
    unsigned int mVar;
};

Test obj;

thread.start(&obj) //Внутри потока запускается obj->write();

//В основном потоке
obj.read();

Вот случай, когда в основном потоке создается объект класса. Далее создается доп. поток, которому передается указатель на объект. Поток в свою очередь запускает метод объекта, обращаясь к его внутренним переменным.
Ну и из основного потока мы тоже запускаем метод доступа обращающийся к переменной объекта...
В данном случае для обоих потоков переменная объекта mVar является общей и доступ к ней нужно оформлять через CriticalSection или же нет?
11
12 мая 2010 года
oxotnik333
2.9K / / 03.08.2007
Цитата: Gigahard

В данном случае для обоих потоков переменная объекта mVar является общей и доступ к ней нужно оформлять через CriticalSection или же нет?


если общая, то надо синхронизировать

590
12 мая 2010 года
Gigahard
223 / / 03.04.2006
Да, вот я как бы и спрашиваю - в данном случае общая или нет? :)
11
12 мая 2010 года
oxotnik333
2.9K / / 03.08.2007
ну сам то подумай: экземпляр класса один создается, соотв. внутренний член тоже в единственном экземпляре будет.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог