我需要在Win7 x64上實現與此函數相同的功能。Windows C++等價於Java的LockSupport.parkNanos()
我最初使用SwitchToThread()
但這不起作用,因爲它會在極端條件下導致死鎖。我能找到的唯一選擇是Sleep()
,但這可能是一個性能殺手,因爲它只能以毫秒分辨率工作,我仍然不確定它是否與LockSupport.parkNanos()
一樣。
我發現Java的計劃能力(如果這是發生了什麼事情)的線程在納秒間隔可疑,所以我實現了我只能假設他們做...旋轉。然而,我不確定這是否能解決問題,它可能僅僅是推遲了不可避免的,因爲看起來Java函數需要JVM的干預才能工作。沒有parkNanos
的源代碼可用;它在本地Sun庫中實現。
class LockSupport
{
public:
static void ParkNanos(unsigned __int64 aNanos)
{
ULONGLONG start;
ULONGLONG end;
::QueryUnbiasedInterruptTime(&start);
do
{
// My issue with this is that nothing is actually 'Parked'.
::SwitchToThread();
::QueryUnbiasedInterruptTime(&end);
}
while ((end - start) < aNanos);
}
};
調用代碼看起來是這樣的:
void SomeClass::SomeFunction()
{
while (someCond)
{
LockSupport.parkNanos(1L);
}
}
FWIW,我移植LMAX的干擾器模式C++。當一個線程處於SingleThreadedClaimStrategy::WaitForFreeSlotAt()
而另一個線程處於BlockingWaitStrategy::WaitFor
(無超時)時,會發生死鎖。當RingBuffer大小很小時,死鎖就更加明顯...... 1,2,4,8等。
這些線程是由正常的CreateThread
手段創建的。
編輯:當我寫這個的時候已經很晚了,所以這裏有一些更多的信息。 RingBuffer持有__int64
s。我有一個生產者線程和一個消費者線程。消費者線程還生成一個Timer線程,該線程每秒鐘輪詢消費者使用它上次使用的事件的序列號。當消費者沒有取得進展並且製片人還沒有完成時,就有一個問題出現。製片人僅僅是在發行計數器的幾百萬次循環中運行。所以,我的輸出看起來是這樣的:
898
97
131
Timer: no progress
Timer: no progress
...
這是唯一真正可重複的發佈模式,一切的速度進行了優化。
你說你用':: SwitchToThread()'死鎖了。它返回真或假? – Managu 2012-08-16 03:51:47
@Managu在正常執行期間,它可以返回兩者。然而,你的評論給了我這個函數旋轉的想法,而它返回false。 – James 2012-08-16 12:55:47
你是如何實現ReentrantLock和Condition的,就像BlockingWaitStrategy所使用的那樣?你的鎖定實現是否可重入?條件變量是否以原子方式獲取/釋放相應的鎖? – Managu 2012-08-17 01:40:21