Я создаю небольшое приложение, которое имеет поток рендеринга и несколько рабочих потоков для задач, которые могут быть выполнены рядом с рендерингом, например загрузка файлов на какой-либо сервер. Теперь в этих рабочих потоках я использую различные объекты для хранения информации обратной связи и делюсь ею с потоком рендеринга, чтобы прочитать их с целью вывода. Так что render = output, worker = input. Такими общими объектами являются int, float, bool, строка STL и список STL.
У меня это работало несколько месяцев, и все было в порядке, за исключением 2 случайных сбоев во время вывода, но теперь я узнал о синхронизации потоков. Я читаю int, bool и т. Д. Не требуется синхронизация, и я думаю, что это имеет смысл, но когда я смотрю на строку и список, я боюсь возможных сбоев, если два потока пытаются прочитать / записать объект одновременно. По сути, я ожидаю, что один поток изменяет размер строки, в то время как другой может использовать устаревший размер для циклического перебора его символов и последующего чтения из нераспределенной памяти. Сегодня вечером я хочу построить небольшой тестовый сценарий с 2-мя потоками, пишущими / читающими один и тот же объект в цикле, однако я надеялся получить некоторые идеи здесь.
Я читал о CriticalSection в Win32 и подумал, что стоит попробовать. И все же я не уверен, как лучше всего это реализовать. Если я поместил его в начале и в конце чтения / функции, я чувствую, что некоторое время было потрачено впустую. И если я обертываю EnterCriticalSection и LeaveCriticalSection в Set и Get Functions для каждого объекта, который я хочу синхронизировать между потоками, это большая администрация.
Я думаю, что мне нужно пролистать больше ссылок.
Хорошо, я все еще не знаю, как поступить. Я изучал ссылки, предоставленные StackedCrooked, но до сих пор не представляю, как это сделать.
Я сейчас скопировал / изменил это вместе и понятия не имею, как продолжить или что делать: у кого-то есть идеи?
class CSync
{
public:
CSync()
: m_isEnter(false)
{ InitializeCriticalSection(&m_CriticalSection); }
~CSync()
{ DeleteCriticalSection(&m_CriticalSection); }
bool TryEnter()
{
m_isEnter = TryEnterCriticalSection(&m_CriticalSection)==0 ? false:true;
return m_isEnter;
}
void Enter()
{
if(!m_isEnter)
{
EnterCriticalSection(&m_CriticalSection);
m_isEnter=true;
}
}
void Leave()
{
if(m_isEnter)
{
LeaveCriticalSection(&m_CriticalSection);
m_isEnter=false;
}
}
private:
CRITICAL_SECTION m_CriticalSection;
bool m_isEnter;
};
/* not needed
class CLockGuard
{
public:
CLockGuard(CSync& refSync) : m_refSync(refSync) { Lock(); }
~CLockGuard() { Unlock(); }
private:
CSync& m_refSync;
CLockGuard(const CLockGuard &refcSource);
CLockGuard& operator=(const CLockGuard& refcSource);
void Lock() { m_refSync.Enter(); }
void Unlock() { m_refSync.Leave(); }
};*/
template<class T> class Wrap
{
public:
Wrap(T* pp, const CSync& sync)
: p(pp)
, m_refSync(refSync)
{}
Call_proxy<T> operator->() { m_refSync.Enter(); return Call_proxy<T>(p); }
private:
T* p;
CSync& m_refSync;
};
template<class T> class Call_proxy
{
public:
Call_proxy(T* pp, const CSync& sync)
: p(pp)
, m_refSync(refSync)
{}
~Call_proxy() { m_refSync.Leave(); }
T* operator->() { return p; }
private:
T* p;
CSync& m_refSync;
};
int main
{
CSync sync;
Wrap<string> safeVar(new string);
// safeVar what now?
return 0;
};
Ладно, сейчас я готовил небольшой тест, чтобы проверить, насколько удачны мои попытки, поэтому сначала я создал настройку для сбоя приложения, я поверил…
Но это не сбой !? Значит ли это, что теперь мне не нужна синхронизация? Что нужно программе для эффективного сбоя? И если он не падает, почему я вообще беспокоюсь. Кажется, я снова упускаю какой-то момент. Есть идеи?
string gl_str, str_test;
void thread1()
{
while(true)
{
gl_str = "12345";
str_test = gl_str;
}
};
void thread2()
{
while(true)
{
gl_str = "123456789";
str_test = gl_str;
}
};
CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)thread1, NULL, 0, NULL );
CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)thread2, NULL, 0, NULL );
Только что добавил больше материала, и теперь он вылетает при вызове clear (). Хорошо.
void thread1()
{
while(true)
{
gl_str = "12345";
str_test = gl_str;
gl_str.clear();
gl_int = 124;
}
};
void thread2()
{
while(true)
{
gl_str = "123456789";
str_test = gl_str;
gl_str.clear();
if(gl_str.empty())
gl_str = "aaaaaaaaaaaaa";
gl_int = 244;
if(gl_int==124)
gl_str.clear();
}
};