2012-08-16 55 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