2015-01-20 5 views
0

Delphi Indy Server 및 ThreadSafe 변수를 더 잘 이해하려고합니다.전역 원자 변수가 TIdHTTPServer.OnCommandGet threadsafe 내부에서 사용됩니까?

필자는 Delphi Indy 웹 서버에 "히트 수"의 간단한 카운터를 원한다고 말합니다. 안부 확인이 구현은 안전을 스레드에

procedure MyWebServer.CommandGet(AContext: TIdContext; 
    ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); 
begin 
    GlobalWebHits := GlobalWebHits+1; 
    ..... 
end; 

: 그래서

var: GlobalWebHits: Integer 

그리고 TIdHttpServer.OnCommandGet 내 처리기 내부

내가 그것을 증가 글로벌 정수를 선언? 두 스레드가 동시에 GlobalWebHits를 업데이트하려고 할 가능성이 있습니까?

중요 섹션에서 증분을 래핑해야합니까?

+0

"원자 변수"라는 용어는 간단한 읽기 또는 쓰기 작업을 가정합니다. 다른 작업에는 항상 일종의 동기화가 필요합니다 (적어도 Intel x86 또는 x64 CPU의 경우 해당) – kludg

답변

2

원자 변수와 같은 것은 없습니다. 작업은 원자적일 수도 있고 아닐 수도 있습니다.

GlobalWebHits := GlobalWebHits+1; 

이 것은 원자가 아닙니다. 별도의 읽기, 수정 및 쓰기 단계가 있습니다.

당신은 중요한 부분을 사용할 수 있지만, 원자 작업을 사용하는 것이 더 간단하고 효율적입니다 :에 따라

AtomicIncrement(GlobalWebHits); 

또는

TInterlocked.Increment(GlobalWebHits); 

또는

InterlockedIncrement(GlobalWebHits); 

를 델파이 당신이 사용하는 버전.

+0

고마워요. 마지막 버전 (InterlockedIncrement)은 Delphi2007에서 나를 위해 일했습니다. 질문 : 원래 구현에서 GlobalWebHits가 "손상됨"(즉, 두 스레드가 동시에 쓰는) 결과는 무엇입니까? 이것은 단지 하나의 카피가 다른 카피를 덮어 쓰게 할까? 아니면 서버가 불안정해질 수있는보다 체계적인 효과가있을 수 있습니까? –

+1

잘못된 데이터가 있습니다. 스레드 A는 0을 읽고 증분 한 다음 씁니다. 이 시간 동안 스레드 B는 0을 읽고 증분 한 다음 씁니다. 최종 결과는 변수가 2를 보유해야 할 때 변수가 1을 보유한다는 것입니다. 이것은 고전적인 표준 데이터 경쟁입니다. 일부 데이터 경주는 양성입니다. 내가 추측하는이 것은 아니다. –

+0

감사합니다. 훌륭한 설명입니다. 그것은 로깅 카운터 일 뿐이며보고를 제외하고는 아무런 중요한 측면에서 사용되지 않습니다. 그래서이 경우에는 양성입니다. 그러나이 같은 위반이 시스템 불안정을 초래할 수 있다면 나는 단지 궁금했다. –