我需要在 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
s。我有一个生产者线程和一个消费者线程。Consumer 线程还生成一个 Timer 线程,该线程每秒轮询 Consumer 以获取它上次消费的事件的序列号。当消费者没有进展并且生产者也没有完成时,就会出现这样的情况。Producer 只是在循环中运行了几亿次,发布了一个计数器。所以我的输出看起来像这样:
898
97
131
Timer: no progress
Timer: no progress
...
它只有在发布模式下才能真正重现,一切都针对速度进行了优化。