我有一些數據是由多個線程讀取和更新。讀取和寫入都必須是原子的。我想這樣做是這樣的:無鎖讀寫器
// Values must be read and updated atomically
struct SValues
{
double a;
double b;
double c;
double d;
};
class Test
{
public:
Test()
{
m_pValues = &m_values;
}
SValues* LockAndGet()
{
// Spin forver until we got ownership of the pointer
while (true)
{
SValues* pValues = (SValues*)::InterlockedExchange((long*)m_pValues, 0xffffffff);
if (pValues != (SValues*)0xffffffff)
{
return pValues;
}
}
}
void Unlock(SValues* pValues)
{
// Return the pointer so other threads can lock it
::InterlockedExchange((long*)m_pValues, (long)pValues);
}
private:
SValues* m_pValues;
SValues m_values;
};
void TestFunc()
{
Test test;
SValues* pValues = test.LockAndGet();
// Update or read values
test.Unlock(pValues);
}
的數據被竊取的指針,它保護每一個讀取和寫入,這應該使線程安全的,但它需要每一個訪問提供了兩個互鎖的指令。將有大量的讀取和寫入,並且我不能預先告知是否會有更多的讀取或更多的寫入。
它可以做得比這更有效嗎?這在閱讀時也會鎖定,但由於可能有更多的寫入,所以閱讀沒有任何優化閱讀的意義,除非它不會對寫作造成損失。
我正在考慮在沒有互鎖指令(連同序列號)的情況下獲取指針的讀取操作,複製數據,然後有一種方法告訴序列號是否已更改,在這種情況下應該重試。但是,這需要一些記憶障礙,我不知道它是否能夠提高速度。
-----編輯-----
感謝所有的好評!我實際上沒有運行這個代碼,但我會嘗試今天晚些時候將當前方法與關鍵部分進行比較(如果我獲得時間)。我仍然在尋找最佳的解決方案,所以稍後我會回到更高級的評論。再次感謝!
什麼是使用默認的線程同步原語的問題? – naivnomore 2010-07-29 06:29:07
我必須承認,我只是假設我能做得更快。 1)我只在這裏顯示一個實例,但實際上我可能會有這些受保護的數據記錄的10000個實例,這將意味着10000個關鍵部分。但也許這不是問題,我不知道,我從來沒有嘗試過這樣的事情。 2)我希望我能拿出比關鍵部分更快的東西。每秒可以輕鬆實現數百萬次讀/寫。而在個人層面上,我認爲讓它像人性化(機器化)一樣快是有趣的。 – Rabbit 2010-07-29 06:49:06
Windows CRITICAL_SECTION非常輕便,除非實際上必須阻止。我不認爲像這樣忙着等待用戶線程是一個非常好的主意 - 你隱式地告訴調度程序,你有很多事情要做,而實際上情況正好相反。 – 2010-07-29 07:46:54