2012-08-16 56 views
3

我需要在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 
... 

這是唯一真正可重複的發佈模式,一切的速度進行了優化。

+0

你說你用':: SwitchToThread()'死鎖了。它返回真或假? – Managu 2012-08-16 03:51:47

+0

@Managu在正常執行期間,它可以返回兩者。然而,你的評論給了我這個函數旋轉的想法,而它返回false。 – James 2012-08-16 12:55:47

+0

你是如何實現ReentrantLock和Condition的,就像BlockingWaitStrategy所使用的那樣?你的鎖定實現是否可重入?條件變量是否以原子方式獲取/釋放相應的鎖? – Managu 2012-08-17 01:40:21

回答

3

除了能夠unpark()一個線程,LockSupport.parkNanos(...)只不過是一個睡眠。在Windows上的OpenJDK Hotspot VM中,它使用WaitForSingleObject(...),它的編號爲implemented(4436行),睡眠時間最少爲1ms。

LMAX干擾程序似乎不是unpark()線程。因此,您應該通過致電Sleep(1)獲得同等的行爲。你可以用Sleep(0)做得更好:在當前線程中放棄剩下的時間片,並可以立即重新調度。這相當於SwitchToThread(),只是後者可能會告訴你「還沒有準備好運行,所以你可以保留CPU。」另一方面,如果您的調度粒度足夠低,Sleep(1)實際上可能會暫停1毫秒。

remarksSleep()注意到您可以通過調用timeBeginPeriod()來提高系統的調度粒度(可能會降低到每個tick的1ms)。

2

沒有parkNanos的源代碼可用;它在本地Sun庫中實現。

該本地庫的源代碼應該是OpenJDK 6/7源代碼的一部分,因此應該可以下載或瀏覽。

+0

這表明''parkNanos()'在windows上等待只有毫秒的分辨率:http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/os/windows/vm/os_windows.cpp,行4451 – Managu 2012-08-16 03:35:19

+0

我搜索和搜索,但無法找到那。謝謝 – James 2012-08-16 12:52:51