2010-12-07 4 views
0

대용량의 데이터 (백그라운드 스레드에 의해)로 미리로드되고 전체로드 될 때까지 사용할 수없는 캐시가 있습니다 (너무 자주 다시로드되고로드하는 동안 사용할 수 없게됩니다) . 액세스하기 전에 플래그를 확인하는 데 사용하는 클래스가 필요합니다. isLoaded() 나는이 같은 액세스 제어를위한 ReentrantReadWriteLock (나는 단순함의 코드에서 이것을 생략) 사용 ReentrantReadWriteLock 및 부울 플래그 사용

if (cache.isLoaded()) { 
    try { 
     Object x = cache.get(y); 
    } catch (IllegalStateException iex) { 
     // goto database for object 
    } 
} else { 
    // goto database for object 
} 

가 정말 필요합니까 :
public class Cache { 

    private volatile boolean loaded = false; //starts false 

    private static String[] cache; 

    private static Lock readLock; 
    private static Lock writeLock; 

    public Object get(Object key) { 
     if (!readLock.tryLock()) throw IllegalStateException(...); 
     try { 
      ... do some work 
     } finally { 
      readLock.unlock(); 
     } 
    } 

    // called by background thread 
    private void loadFull() { 
     loaded = false; 
     writeLock.lock() 
     try { 
      cache = new String[]; 
      ... fill cache 
     } finally { 
      writeLock.unlock(); 
      loaded = true; 
     } 
    } 
.... 
} 

지금 내 다른 클래스에서이 같은 블록을 가지고 try/catch? 플래그가 false로 설정되고 readLock try()가 실패 할 가능성이 있습니까? 나는 플래그와 성가신 사실을 신경 써야 할까? (플래그가 false 인 것처럼 예외가 던져지면 기본적으로 동일한 코드를 수행하기 때문에) 예외를 잡아야한다. 나는 약간의 잘못하고있는 것처럼 느껴진다. 그러나 나는 그것에 손가락을 넣을 수 없다. 감사.

+0

[캐시] (http : //en.wikipedia.org/wiki/Cache) 그리고 나는 우리가 당신이 [생산자/소비자 문제] (http://en.wikipedia.org/wiki/Producer-consumer_problem)를 해결하려고 노력하지 않았다. BTW,'IllegalStateException'은 사용할 적절한 것이 아닙니다. AFAI는 비어있는 캐시가 응용 프로그램에서 일반적인 것임을 이해합니다. – khachik

+0

기존의 경량 캐싱 솔루션을 사용할 수없는 특별한 이유가 있습니까? –

+0

별도의 읽기 및 쓰기 잠금이 필요합니까? 그리고 String [] 캐시는 새로운 int []로 생성됩니다. – extraneon

답변

2

정말 시도/잡을 필요하십니까? 플래그가 이 false로 설정되고 readLock try()가 이 실패 할 가능성이 있습니까?

네, 필요합니다. cache.isLoaded()cache.get() 사이에서 작성자가 들어 와서 쓰기 잠금을 얻을 수 있습니다.이 경우 cache.isLoaded()true을 반환하지만 cache.get()은 예외를 throw합니다.

나는 심지어 플래그를 귀찮게해야하고합니다 ( 예외가 플래그가 false 경우로 던져진다면 나는 기본적으로 동일한 코드를 할 때문에) 돌기는 예외를 잡을 수있어.

표시 한 코드에서 get이 읽기 ​​잠금을 얻지 못한 경우에만 예외가 발생합니다. 동시 기록기가있는 경우에만 읽기 잠금 획득이 실패합니다. isLoaded도이 시나리오에서 false를 반환합니다. 따라서 예외에 의존하는 것만으로 충분합니다. 또한 전문화 된 CacheStaleException을 만드는 것을 고려해보십시오.

1

다른 스레드가 이미 해당 잠금을 획득 한 경우 tryLock이 실패합니다. 이는 일반적으로 클라이언트가 높은 경합 (동일한 캐시에 액세스하는 여러 클라이언트)으로 인해 잠금을 획득하지 못하면 예외가 발생 함을 의미합니다. 이러한 상황을 다루는 클라이언트 계층에서 구현 한 대체 전략이 있습니까?

static이 잠겨 있습니까? 캐시가 일반적으로 애플리케이션에서 싱글 톤으로 사용 되더라도 Locks를 정적으로 만들어 사용성을 제한 할 필요가 없다고 생각합니다.

+0

잠금을 정적으로 제한하는 방법은 무엇입니까? – Gandalf

+0

@ 간달프 : 다중 캐시 인스턴스가 동일한 잠금을 사용하여 종료됩니다. –

+0

Ahh는 기본적으로 싱글 톤입니다. 단 하나만 생성됩니다. – Gandalf

0

아니요. 귀하의 패러다임이 혼란 스럽습니다. 아마도 실제 데이터베이스로 이동하는 것은 비용이 많이 들며 캐시의 목적입니다. 캐시가 다시로드되는 경우에는 캐시가 대기 될 때까지 기다리지 않는 것이 좋습니다.

읽기 잠금을 즉시 사용할 수없는 경우 당신이 정말로 데이터베이스에 가고 싶어 할 가정, 내가 이런 짓을 했을까 :

public Object get(Object key) { 
     Object returnValue; 
     if (readLock.tryLock()) { 
      try { 
       ... do some work 
       returnValue = ... 
      } finally { 
       readLock.unlock(); 
      } 
     } else { 
      //go to database 
      returnValue = ... 
     } 
     return returnValue; 
    } 
+0

OP의 의도는 'Cache'클래스가 캐싱 대상을 모르는 것입니다. 따라서 데이터를 가져 오는 논리는 'Cache'클래스 외부에서 유지됩니다. 그럼에도 불구하고 Tim과 재시도 논리를 유지하는 것이 더 낫다는 것에 동의한다. 아마도 'Cache'를 래핑하는 또 다른 클래스와 그 클래스를 사용하는 클라이언트가 될 것이다. –

+0

그 논리는 캐시 외부에서 처리됩니다. 두 번째 코드 블록에서는 "다른 클래스에서"라고 말합니다. String [] 캐시는 한 번에 모두로드되며 잠시 동안 소요되므로 readLock 호출이 실패하면 캐시가 비어 있고 요청시로드되지 않는다는 의미입니다. – Gandalf

관련 문제