Синхронизация потоков в C ++ / CLI с использованием только атомарных операций - PullRequest
2 голосов
/ 03 февраля 2011

В настоящее время я пытаюсь добиться синхронизации потоков в C ++ .net, используя только атомарные операции с использованием класса System :: Threading :: Interlocked в .net. Я не очень опытен с многопоточностью, и я пытаюсь использовать синхронизацию потоков без блокировки. В настоящее время я создал класс с именем settings, который содержит статические переменные, которые мне нужно разделить между потоками. Затем я создал в нем две статические функции: одну для установки элементов статических данных и одну для их чтения. В настоящее время именно так выглядит одна из моих статических функций синхронизации. Я понимаю, что, если в эту функцию одновременно войдут более двух потоков, они могут застрять в цикле while навсегда, но эта функция понадобится только двум потокам , поток с графическим интерфейсом и основной поток, читать настройки и отправлять работу в рабочие потоки.


//object is handle to instance of settings class that also contains non-static
//members that will contain each threads copy of the data.
void Settings::SetStaticVariables(Settings ^object)
{
    int returnvalue;

    //canchange variable is a static integer of the class "Settings"
    returnvalue = Threading::Interlocked::Increment(Settings::canchange);
    if(returnvalue > 1)
    {
        while(Settings::canchange > 1)
        {
            //perhaps eventually I will find an alternative to telling the thread
            //to sleep for a defined amount of time, maybe when I learn how to use events
            //for now this will do, speed is not very important for this data sync as 
            //it does not occure often
            Threading::Thread::Sleep(50);
        }
    }
    //data synchronization of static members here

    //decrement allowing waiting threads to exit while loop
    Threading::Interlocked::Decrement(Settings::canchange);
};

У меня вопрос: видите ли вы что-нибудь некорректное, что не даст мне того, чего я ожидаю, или эта идея синхронизации некорректна?

1 Ответ

2 голосов
/ 04 февраля 2011

Вы хорошо разбираетесь в многопоточности, если смогли определить, что это безопасно только для двух потоков.Не позволяйте людям отговаривать вас от изучения техник без блокировки.

Вы можете использовать InterlockedExchange вместо приращения, что устранит возможную тупиковую ситуацию с> = 2 потоками.Однако этот алгоритм вовсе не является программированием без блокировок, скорее вы реализуете свою собственную блокировку.Конечно, это означает, что вы столкнетесь со многими проблемами производительности и корректности, которые уже были решены классами блокировки библиотеки (Monitor и друзьями).

Вот как это будет выглядеть с Interlocked::Exchange

// try to acquire lock
while (0 != Interlocked::Exchange(Settings::canchange, 1))
{
   Thread::Sleep(50);
}

MemoryBarrierAcquire();

// update shared variables

// flush cached writes
MemoryBarrierRelease();
// unlock
Settings::canchange = 0;
...