當雙緩衝的數據這是由於被線程之間共享執行指針交換,我使用一個系統,其中一個線程從一個緩衝器讀出,一個線程從另一個緩衝器讀出和讀出從第一個緩衝區。麻煩的是,我將如何實現指針交換?我需要使用關鍵部分嗎?沒有互鎖功能可以實際交換數值。我不能讓線程從緩衝區讀取一個,然後開始從緩衝區讀取兩個,在讀取的過程中,這將是appcrash,即使其他線程沒有開始寫入。在雙緩衝的多線程系統
我在Visual Studio Ultimate 2010 RC的Windows上使用本機C++。
當雙緩衝的數據這是由於被線程之間共享執行指針交換,我使用一個系統,其中一個線程從一個緩衝器讀出,一個線程從另一個緩衝器讀出和讀出從第一個緩衝區。麻煩的是,我將如何實現指針交換?我需要使用關鍵部分嗎?沒有互鎖功能可以實際交換數值。我不能讓線程從緩衝區讀取一個,然後開始從緩衝區讀取兩個,在讀取的過程中,這將是appcrash,即使其他線程沒有開始寫入。在雙緩衝的多線程系統
我在Visual Studio Ultimate 2010 RC的Windows上使用本機C++。
爲什麼不能使用InterlockedExchangePointer?
編輯:好吧,我給你說的話,現在,IEP實際上不換2點彼此生活的指針,因爲它只能通過引用,採用一個單值。
如果您是InterlockedExchangePointer,則只能在呼叫中實際影響一個指針。這意味着爲了交換所有三個指標,我需要三個電話 - 在中間留下一個空白。 InterlockedExchangePointer實際上是一個用詞不當,它只會給給定值的給定指針。我預計它會交換一對指針(正是出於這個原因)。即使它的確如此工作,但如果不暫停這兩個線程來執行更新,我仍然無法實際使用它,這是我真正想避免的。 – DeadMG 2010-02-15 20:39:23
@DeadMG:'buf1 = InterlockedExchangePointer(&buf2,buf1);'如果你從當前使用buf1的線程調用它,我認爲它會做你想做的。但我不完全確定你的意思是「所有三個指針」。 – Dan 2010-02-15 22:45:30
我有一個來自渲染的緩衝區,一個來自遊戲邏輯的緩衝區(所以它們都可以讀取緩衝區),然後一個緩衝區以供遊戲邏輯寫入。問題是您調用的等價操作符不一定是原子 - InterlockedExchangePointer和buf1 =之間存在差距。即使沒有,在這種情況下,仍然沒有機制來確保我不在渲染過程中。 我認爲在另一個答案中描述的讀寫互斥解決方案可能是最好的。 – DeadMG 2010-02-15 23:05:20
使用關鍵部分是可以接受的方式。只需在你的指針操作/緩衝區讀/寫代碼周圍共享一個CRITICAL_SECTION
對象,並在該對象上調用EnterCriticalSection
和LeaveCriticalSection
。嘗試儘快完成關鍵部分,儘可能在關鍵部分之外留下儘可能多的代碼。
即使你使用雙聯鎖交流技巧,你仍然需要一個臨界區或東西同步線程,所以還不如將其用於這個目的了。
您必須構建自己的函數來交換使用信號量或臨界區的指針來控制它。需要將相同的保護添加到指針的所有用戶,因爲讀取正在被修改的指針的任何代碼是不好的。
管理這個的一種方法是讓所有指針操作邏輯在鎖的保護下工作。
請參閱我最初設計的線程,以使它們完全異步,並且不需要在常規操作中進行任何同步。但是,因爲我在線程池中以每個對象爲基礎執行操作,所以如果給定的對象由於當前正在同步而不可讀,那麼在等待時我可以再做一次。從某種意義上說,我可以同時等待和操作,因爲我有很多線索可以解決。
創建兩個關鍵部分,每個線程一個。 渲染時,按住渲染暴擊部分。另一個線程仍然可以做到它喜歡的其他爆擊部分。使用TryEnterCriticalSection,如果它被保留,則返回false,並將該對象添加到列表中以稍後重新呈現。這應該允許我們繼續渲染,即使給定的對象當前正在更新。 更新時,同時保留兩個暴擊部分。 在進行遊戲邏輯的同時,保持遊戲邏輯暴擊部分。如果已經存在,那就沒有問題了,因爲我們的線程比實際的處理器多。所以如果這個線程被阻塞,那麼另一個線程將只使用CPU時間,這不需要管理。
您還沒有提及您的Windows平臺限制,但是如果您不需要與Windows Server 2003或客戶端上的Vista相比較舊版本的兼容性,則可以使用InterlockedExchange64()函數來交換64位值。通過將兩個32位指針打包爲64位對結構,可以有效地交換兩個指針。
有通常的Interlocked * variantions; InterlockedExchangeAcquire64(),InterlockedCompareExchange64()等...
如果你需要運行,比如XP,我會去一個關鍵部分。當爭用的可能性很低時,它們表現相當好。
我很樂意考慮不在XP上運行。但是,它並沒有解決交換中間渲染指針的問題。 – DeadMG 2010-02-15 21:24:40
這聽起來像是一個讀寫器互斥類型的問題。
假設您有兩個緩衝區B1和B2,並且您有兩個線程T1和T2。如果T1正在使用B1而T2正在使用B2,則可以。 「使用」是指讀取和/或寫入緩衝區。然後在某個時候,緩衝區需要交換,以便T1使用B2,而T2使用B1。你必須小心的是,交換是在兩個線程都不訪問緩衝區的情況下完成的。
假設您只使用了一個簡單的互斥鎖。 T1可以獲得互斥體並使用B1。如果T2想要使用B2,它必須等待互斥鎖。當T1完成時,T2將解除阻塞並與B2一起工作。如果任一線程(或某個第三方線程)想要交換緩衝區,則它也必須採用互斥鎖。因此,只使用一個互斥量序列化訪問緩衝區 - 不太好。
如果您改用讀寫器互斥鎖,它可能會更好。 T1可以獲得對互斥鎖的讀鎖,並使用B1。 T2也可以獲得對互斥鎖的讀鎖,並使用B2。當其中一個線程(或第三方線程)決定交換緩衝區時,它將不得不對互斥鎖執行寫入鎖定。直到沒有更多的讀鎖,它將無法獲得寫鎖。此時,它可以交換緩衝區指針,知道沒有人使用任何一個緩衝區,因爲當互斥鎖上存在寫入鎖定時,所有嘗試讀取鎖定的操作都將被阻止。
一個有趣的解決方案 - 幾乎和我以前一樣,除了更清潔。但是,我無法在MSDN上找到關於這種互斥體的任何文檔。它們是WinAPI的固有組成部分,還是我必須自己編寫代碼? – DeadMG 2010-02-15 23:02:37
打敗我。我谷歌'讀者作家互斥窗口',並發現這一點:http://msdn.microsoft.com/en-us/magazine/cc163599.aspx - 有幫助嗎?谷歌沒有'windows'來讀理論...... – Dan 2010-02-16 01:52:28
如果傳入數據的順序很重要,那麼仍然需要同步。無論讀者/寫者互斥,閱讀者在繼續之前都必須等待新的數據到達。 – 2011-03-25 15:40:19
你是什麼意思?「沒有互鎖功能可以實際交換值。」?爲什麼你不能使用這些功能? – AndiDog 2010-02-15 20:33:20