2012-08-16 1 views
3

Win7 x64에서는이 기능과 동일한 기능을 구현해야합니다.Java의 LockSupport.parkNanos()와 동일한 Windows C++

처음에는 SwitchToThread()을 사용했지만 극한 상황에서 교착 상태가 발생하기 때문에이 방법은 작동하지 않습니다. 내가 찾을 수있는 유일한 대안은 Sleep()입니다. 아직 밀리 초 해상도에서만 작동하므로 성능 희생자가 될 가능성이 높습니다. 그래도 여전히 LockSupport.parkNanos()과 같은 작업을 수행하는지 확신 할 수 없습니다.

의심 스럽지만 나노초 간격으로 스레드를 스케줄링 할 수있는 자바의 기능을 발견 했으니까요. 그러나 이것이이 문제를 해결하는지 확신 할 수는 없지만 자바 기능이 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, 나는 C에 LMAX의 스럽 패턴을 포팅하고 ++. 교착 상태는 한 스레드가 SingleThreadedClaimStrategy::WaitForFreeSlotAt()이고 다른 스레드가 BlockingWaitStrategy::WaitFor (시간 초과 없음) 일 때 발생합니다. 교착 상태는 RingBuffer 크기가 1, 2, 4, 8 등일 때 더욱 분명합니다.

스레드는 보통 CreateThread 수단으로 생성됩니다.

편집 : 제가 이것을 작성했을 때 꽤 늦었습니다. 그래서 여기에 더 많은 정보가 있습니다. RingBuffer에는 __int64이 저장됩니다. 하나의 Producer 스레드와 하나의 Consumer 스레드가 있습니다. 또한 Consumer 스레드는 마지막으로 소비 한 이벤트의 시퀀스 번호에 대해 매 초 Consumer를 폴링하는 Timer 스레드를 생성합니다. 소비자가 아무런 진전을 보이지 않고 생산자도 끝나지 않은 시점이 있습니다. 프로듀서는 카운터를 게시하는 데 수억 번 반복됩니다. 따라서 내 출력은 다음과 같습니다.

898 
97 
131 
Timer: no progress 
Timer: no progress 
... 

속도는 모두 최적화 된 릴리스 모드에서만 재생됩니다.

+0

당신은':: SwitchToThread()'로 교착 상태에 빠졌다고합니다. 진실한가 거짓인가? – Managu

+0

@Managu 정상 실행 중에는 두 가지 모두를 반환 할 수 있습니다. 그러나 귀하의 의견은 나에게 거짓을 반환하는 동안이 기능을 회전시키는 아이디어를주었습니다. – James

+0

BlockingWaitStrategy에서 사용하는 ReentrantLock 및 Condition은 어떻게 구현하고 있습니까? 잠금 구현이 재진입 성입니까? 조건 변수가 원자 적으로 해당 잠금을 획득하거나 해제합니까? – Managu

답변

3

unpark() 스레드 이외의 기능 외에, LockSupport.parkNanos(...)은 수면에 지나지 않습니다. Windows의 OpenJDK Hotspot VM에서 (줄 4436)은 WaitForSingleObject(...)을 사용하고 최소 1ms 동안 대기합니다.

LMAX disruptor는 unpark() 스레드로 보이지 않습니다. 따라서 Sleep(1)을 호출하여 동등한 동작을 얻어야합니다. Sleep(0)을 사용하면 더 잘할 수 있습니다. 현재 스레드에서 나머지 시간 조각을 포기하고 즉시 다시 스케줄 할 수 있습니다. 이것은 SwitchToThread()과 동일하지만, 후자가 "아직 실행할 준비가되지 않은 것이므로 CPU를 유지할 수 있습니다."라고 말할 수도 있습니다. 반면에 Sleep(1)은 일정 세분성이 충분히 낮은 경우 실제로 1ms 동안 일시 중지 될 수 있습니다.

remarks ~ Sleep()에서 timeBeginPeriod()을 호출하여 시스템의 일정 세분성을 향상시킬 수 있습니다 (가능한 한 틱당 1 밀리 초까지).

2

parkNanos의 소스 코드가 없습니다. 원시 Sun 라이브러리에서 구현됩니다.

해당 네이티브 라이브러리의 소스 코드는 OpenJDK 6/7 소스 코드의 일부 여야하므로 다운로드하거나 찾아 볼 수 있어야합니다.

+0

이는 윈도우상의'parkNanos()'가 기다리고 있음을 시사한다. 밀리 초 해상도 만 : http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/os/windows/vm/os_windows.cpp, 라인 4451 – Managu

+0

나는 검색했지만 검색하지 못했습니다. 그. 감사 – James