我構建了一個小應用程序,該應用程序具有一個渲染線程和一些輔助線程,用於可在渲染附近進行的任務,例如,將文件上傳到某臺服務器上。現在,在這些工作線程中,我使用不同的對象來存儲反饋信息,並與渲染線程共享這些對象以進行輸出目的的讀取。所以render = output,worker = input。這些共享對象是int,float,bool,STL字符串和STL列表。如何以及在多線程C++中必須同步哪些數據
我有這個運行幾個月,除輸出過程中出現2次隨機崩潰外,其他都很好,但我現在已經瞭解了線程同步。我讀int,bool等不需要同步,我認爲它是有道理的,但是當我查看字符串和列表時,如果兩個線程同時嘗試讀取/寫入對象,我擔心潛在的崩潰。基本上我希望一個線程更改字符串的大小,而另一個線程可能會使用過時的大小循環其字符,然後從未分配的內存中讀取。今天晚上,我想用2個線程編寫/讀取循環中的同一個對象來構建一個小測試場景,但是我希望能夠在這裏獲得一些想法。
我在讀關於Win32中的CriticalSection,並認爲它可能值得一試。但我不確定實現它的最佳方式是什麼。如果我在閱讀/功能的開始和結束時放置它,感覺有時浪費了一些時間。如果我在Set和Get函數中爲EnterCriticalSection和LeaveCriticalSection換行,我想要在線程中同步每個對象,它就是很多管理工具。
我想我必須爬過更多的參考。
好吧我還不確定如何繼續。我正在研究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);
只是增加了更多的東西,現在它調用清除()崩潰。好。
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();
}
};
使用``提供的同步原語。實質上,您應該始終將訪問權限同步到多個線程使用的任何容器。 –
2011-12-14 15:30:15
我也讀過關於互斥鎖的內容,它的本質是,如果我只需要一個進程就可以使用它,這將是一種矯枉過正的做法。 CriticalSection速度更快。 http://msdn.microsoft.com/en-us/library/ms810428.aspx – xezon 2011-12-14 16:22:42