我需要在Win7 x64上实现与此函数相同的功能。
最初我使用了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的Disruptor模式移植到C ++。当一个线程在SingleThreadedClaimStrategy :: WaitForFreeSlotAt()中,另一个线程在BlockingWaitStrategy :: WaitFor(没有超时)中时,会发生死锁。当RingBuffer大小很小时(例如1、2、4、8等),死锁更加明显。
这些线程是通过正常的CreateThread方法创建的。
编辑:我写这篇文章时已经很晚了,所以这里有更多的信息。RingBuffer保存__int64。我有一个生产者线程和一个消费者线程。消费者线程还生成一个计时器线程,每秒钟轮询一次消费者以获取其最后消费的事件的序列号。当消费者没有任何进展而生产者也没有完成时,就会出现问题。生产者只是在循环中运行几亿次发布计数器。因此,我的输出看起来像这样:
898
97
131
Timer: no progress
Timer: no progress
...
这个问题只在Release模式下出现,在所有内容都被优化为速度的情况下才能真正复现。
::SwitchToThread()
时出现了死锁。它返回的是 true 还是 false? - Managuvolatile
原语的读写操作需要进行屏障,但C++并没有这样做。阅读更多关于Disruptor的内容,内存屏障看起来非常重要。 - Managu