2017-01-27 6 views
1

크로스 프로세스 카운터가 필요합니다. 나는 메모리 맵핑 된 파일의 정수를 매핑하고 그것에 Interlocked.Increment을 사용할 수 있지만, 그것은 내게는 Semaphore.Release이 같은 일을하고 프로그래밍 오버 헤드가 적게 든다. 예 :`Semaphore.Release`를 readymade 연동 증가로 사용할 수 있습니까?

var mySem = new Semaphore(0, int.MaxValue, "mySemName"); 

// Get the next number. 
int num = mySem.Release(); 

합리적인 것 같습니까?

+0

@ScottChamberlain, 나는 그것이 옳다고 생각하지 않는다. 'Release'가 증가하고'WaitOne'이 감소합니다. 나는 지금 LINQPad에서 그것을 테스트했다. –

답변

2

짧은 답변 : 예

하지만 ... 당신은 증가 (또는 그것을 감소)를 읽기 위해해야 ​​할 것이다. 슬롯의 현재 수를 읽을 수있는 속성이 없습니다 (실제 슬롯이 아니기 때문에 의미가 있습니다).

+0

'Release'는 카운터를 증가시켜 이전 값을 반환합니다. –

+1

@ dan-gph 그것이 제 요점입니다. 카운터로서 유용하려면 값을 수정하지 않고도 읽을 수있는 능력이 필요할 것입니다. –

+0

좋은 점이 있지만 제 필요에 따라 카운터가 증가 할 때 한 번만 읽으면됩니다. –

2

"rigmarole"은 전문 용어입니다. 적은 오버 헤드로? No.

세마포어는 세마포어 카운터 값이 모든 스레드에서 일관되게 유지되도록하는 특수 알고리즘을 구현합니다. 카운터 값은 검사하기 전에 잠 가야하며 카운터 증가 또는 감소가 완료 될 때까지 잠금이 유지되어야합니다. 잠긴 상태에서 다른 스레드는 대기 (블로킹 인 경우)하거나 단순히 실패 (블로킹이 아닌 경우)하고 나중에 때때로 재 시도 할 수 있습니다.

인터록 증가는 단순히 증가 작업이 원자적임을 보장합니다. 바이트 단위 증가는 CPU 레벨 명령어이기 때문에 바이트의 인터록 된 증분에는 특별한 로직이 필요하지 않습니다. 칩셋에 따라 Word와 DWord의 증가가 아톰 일 수도 아닐 수도 있습니다. 그것이 원자라면, 프레임 워크는 그것을 이용하고, 그렇지 않다면, 프레임 워크는 잠금을 설정하여 다른 스레드가 같은 단어 나 단어 안에서 다른 부분의 메모리를 동시에 증가시키지 않도록합니다 .

거의 모든 시간 동안 인터록 된 증가 및 감소에는 훨씬 적은 오버 헤드가 있습니다.

+0

여기서 프로세서 오버 헤드는 신경 쓰지 않습니다. 프로그래밍 오버 헤드에만 관심이 있습니다. –

+3

참고로 나는 리그 마롤에 관심이 있다고 생각했습니다. –

+0

죄송합니다. 더 정확 했어야합니다. "프로그래밍 오버 헤드"로 변경했습니다. –

1

네, 정상적으로 작동합니다. 그러나 이것은 Semaphore 클래스가 설계된 것이 아닙니다. 코드를 유지하려면 뒤에 오는 가난한 사람을 불쌍히 여기십시오. 그는 모든 Semaphore.WaitOne() 호출이 어디에 있는지 궁금 할 것입니다.

공유 메모리에서 이와 동일한 일을하는 것은 어렵지 않습니다. 여기에 필요한 것은 모두 ...

  string mapname = "{EE9D59F3-18F7-4FB6-B76B-AC1E6902BD9B}"; 
      MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen(mapname, sizeof(int)); 
      MemoryMappedViewAccessor mmva = mmf.CreateViewAccessor(0, sizeof(int)); 
      int count = Interlocked.Increment(ref *(int*)p.ToPointer()); 

그러나 이것은 자랑스럽지 않은 코드입니다./unsafe로 코드를 컴파일해야합니다.

우아한 접근 방식이 없으면 디자인 전제를 다시 방문해야합니다. 왜 처음에는 공유 카운터가 필요합니까? 고유 한 것을 만들려면 각 프로세스에서 GUID를 생성하지 않는 것이 어떻습니까? 합계를 집계하는 경우 서버에 증가분을 게시하는 것이 더 강력한 접근 방법 일 수 있습니다. 당신이 정말로 고성능 계산을 필요로한다면 아마도 C#은 당신의 야망에 맞는 적절한 수단이 아닙니다.

+0

감사합니다. 나는 pinvoke없이 그것을하는 방법을 발견 할 수 없었다.하지만 세마포어로 갔어. 릴리스. 나는 그것이 무엇을하는지 설명하기 위해 Release에 코멘트를했다. 불행히도 디자인에 대해서는 아무 것도 할 수 없습니다. 나는 단지 기존 코드를 수정하려고하고있다. 클라이언트 응용 프로그램과 웹 서비스가 있습니다. 두 가지 모두 멀티 스레드이지만, 쓴 사람은 스레드 또는 그 위험을 이해하지 못했습니다. 그것은 끔찍한 일입니다. 상황이 원하는 순서대로 실행되지 않는 경쟁 조건을 수정하려고합니다. 이를 위해 웹 서비스를 단일 스레드로 만들고 있습니다. 효율성은 중요하지 않습니다. ... –

+0

... 그리고 이렇게하려면 "FIFO 뮤텍스"클래스를 만들었습니다. Windows가 다음에가는 것을 결정하는 일반 뮤텍스와 달리 대기중인 스레드는 FIFO 순서로 대기열에 있습니다. 그 명령을 내리려면 글로벌 카운터가 필요합니다 (슈퍼마켓의 델리 카운터에서 번호를받는 것과 같습니다). 그것은 여전히 ​​끔찍하지만, 내가 가진 시간에 할 수있는 최선의 방법입니다. –