2014-12-20 2 views
0

WCF 번역 서비스를 구축 중입니다. 이 서비스는 google translat의 웹 API를 사용합니다. 자주 검색되는 쿼리를 다시 가져 오는 것을 피하기 위해 서비스는 마지막 검색의 메모리 캐시를 유지합니다. 검색 기능은 먼저 캐시를 확인한 다음 Google에 요청을 보냅니다. 마지막으로 중요한 세부 정보 - 요청이 도착할 때마다 키가되도록 문자열을 구성합니다. 검색 용어와 두 언어의 코드로 구성되어 있으므로 특정 검색마다 고유합니다.웹 요청 당 고유 잠금 개체

질문은 다음과 같습니다. 두 개의 정확한 요청이 동시에 도착한다고 가정하면 입력 할 때 이미 입력 된 검색 결과를 찾을 수 있도록 전체 검색 기능에서 두 번째 요청을 잠급니다 첫 번째 캐시에서 캐시로. 다른 요청이 도착하면 나는 그것을 들여 보내고 싶다.

내 생각은 내가 만든 문자열을 사용하여 자물쇠를다는 것이었다. 이것은 정확한 검색 (동일한 검색어, 같은 언어)마다 고유 한 것이기 때문이다. 이것이 내가 설명한 결과를 줄 것입니까?

까지이 글을 읽고에 대한

감사합니다 (:

이 코드 아래 예를 참조하십시오 - 다시 덕분에이 같은

public async Task<TranslationResult> TranslateAsync(Langueges From, Langueges To, string Content) 
{ 
    string key = Content + From.ToString() + To.ToString(); 
    lock(key) 
    { 
     //look for the search result in the cache 
     //if not found, request from google and store result in the memory cache 
    } 
} 
+0

새 문자열에 잠금을 설정하는 것은 의미가 없지만, 다른 모든 스레드를 차단하는 것이 좋습니다. 일부 비동기 알림이 대신 수행하는지 고려하십시오. –

답변

0

뭔가

// this cache is probably going to be the application level cache in asp.net 
// but using Dictionary as an example in this case 
Dictionary<string,TranslationResult> cache = new ... 
private static object syncRoot = new Object(); 

if (!cache.ContainsKey(key) 
{ 
    lock(syncRoot) 
    { 
     // this double checks is not a mistake. 
     // the second request would check for existence of 
     // the key once it acquire the lock 
     if (!cache.ContainsKey(key) { 
      // send request to google then store the result 
     } 
     else { 
      return cache[key]; 
     } 
    } 
} 
else 
{ 
    return cache[key]; 
} 
+0

아마도 외부 if 문 없이는 lock 문을 사용할 수없는 이유가 궁금 할 것입니다. 자물쇠는 존재에 대한 간단한 점검과 비교할 때 매우 비쌉니다. 하루에 수천 건의 조회가 발생할 수 있다는 점을 감안할 때 앱 성능이 아플 거라고 생각합니다. –

+0

:) [이중 확인 잠금] (http://en.wikipedia.org/wiki/Double-checked_locking)이보기보다 어렵습니다. 사전 수정을 시도하여 예기치 않은 임의의 원인이 될 수 있습니다. 오류. –

+0

@ Tien-Dihn : Dictionary 은 스레드로부터 안전하지 않습니다. 다른 스레드가 "... then store the resul"이라는 요소를 추가하는 동안 ContainsKey()를 호출하면 잘못된 읽기가 발생할 수 있습니다. – sevzas

0

을 나는 '당신을 생각하지 않는다!? 변수 "key"는 항상 새로 생성 된 객체가 될 것이고 현재 스레드는 항상 잠금을 즉시 부여 받게 될 것입니다. 문자열 인턴이 여기에있을 것 같지 않습니다. "key"변수가 리터럴이 아니기 때문입니다. "키"가 인턴 된 문자열이면 원하는대로 작동하지만 이상한 부작용이 될 수 있습니다.

어떻게해야합니까? ConcurrentDictionary.GetOrAdd 방법을 사용해보십시오. "핵심"변수가 핵심 인수가됩니다. 키가 캐시에 없으면 valueFactory가 호출됩니다. 귀하의 가치있는 구현은 Google에 전화를 보내야합니다. ConcurrentDictionary는 스레드로부터 안전하기 때문에 명시 적 잠금이 필요하지 않습니다.

0

두 개의 정확한 요청이 동시에 도착한 경우 조직 중 하나를 반환합니다. 어떤 것이 trunslated가 아닌지 알 수 있습니다. 다시 전송하십시오. 나는 이것을 이렇게하기 전에 만들었습니다.