2011-03-24 3 views
1

특정 criterian이 충족되면 테이블 데이터베이스를 해제하는 서버 서비스가 있습니다. 그것은이잠금 문제 : 일부 브레인 스토밍 제안이 필요합니다.

public static void autoUnloadDbTable(final Configuration conf) { 
    final String mKey = getMapKey(conf); 
    final Table table = TABLES.get(mKey); 
    if (table != null) { 
     dblock.getLock().lock(); 
     table.instance.dispose(); 
     TABLES.remove(mKey);.....(2) 
    } 
    //here release lock when done... 
} 

처럼 보이는 그러나 위의 기능이

public Table getTableLocked(final Lock lock) throws FactFinderException { 
    boolean loadTable = true; 
    // Get the current table instance 
    Table table = TABLES.get(mapKey); 
    // .....(1) 
    if (table != null) { 
     //do something 
    } 

    if (loadTable) table = loadTableLocked(table); 

    // lock the table, so the instance don't gets replaced 
    if (lock != null) lock.lock(); 
    return table.instance; 
} 

에서 (1)

실행되고있을 때 내가 하나 개의 스레드가를 실행하는 경우 때문에 뭔가를 둘 필요가 옆으로 실행할 수있는 다른 작업이있다 코드는 (2)이고 다른 스레드는 이미 테이블 객체를 가지고 있지만 (2)는 테이블 객체를 삭제할 것이므로 (1)을 초과하는 모든 것은 올바른 값을 갖지 않을 것입니다. .. 어떤 제안도 제발 ... ?? 당신이 당신의 테이블을 포장 고려할 수 의견을 바탕으로

+0

당신이 table.instance을 반환 한 후에는, autoUnloadDbTable는 여전히 테이블이라고, 따라서 될 수있다. instance.dispose. – richs

답변

0

테이블 주위에 읽기/쓰기 잠금이 필요할 수 있습니다. 테이블에서 무언가를 사용하려면 TABLES.get (...)을 수행하기 전에 읽기 잠금을 가져오고 테이블에서 삭제하려면 TABLES.get (...)을 수행하기 전에 쓰기 잠금을 획득하십시오.

대신 테이블 당 잠금 장치를 사용하는 것이 좋습니다. TABLES.get (...)이 테이블 고유 잠금을 획득 한 후 테이블이 여전히 테이블에 있는지 확인한 다음 잠금을 사용하여 작업을 수행하십시오. 이 테이블 고유 잠금은 읽기/쓰기 잠금이 될 수 있으며 삭제하려는 코드 만 쓰기 잠금을 획득합니다. 이것은 테이블에 추가하려고하면 복잡해지며, 영리해야하고 아마도 테이블에 ConcurrentMap을 사용하고 putIfAbsent를 사용해야합니다.

+0

TABLE = Collections.synchronizedMap 그래서 이미 schyncronised 그래서 당신이 말한 것을하면 효과가 낮아질 것입니다 .... 두번째도 역시 복잡해 보이는 것 같습니다 ... –

+0

첫 번째 것이 더 좋고, 예. 나는 당신이 효율성의 손실을 알아 차릴지 의심 스럽다. 자바에서 잠그는 것은 매우 빠르다. 또한 읽기/쓰기 잠금으로 잠그면 테이블을 일반 맵으로 만들 수 있습니다. – sbridges

0

: 테이블을 삭제할 때

public class LockableTable { 
public Table table; 
public ReadWriteLock lock; 
public LockableTable(Table t){ 
    table = t; 
    lock = .... 
} 
} 

그런 다음 당신은 myLocakbleTable.lock.writeLock().lock()을. 테이크 테이블을 읽을 때의 나머지 시간 myLockableTable.lock.readLock().lock()

+0

아니요 다른 잠금을 볼 수 없으며 Tabbles는 Collections.synchronizedMap입니다. 그래서 (2) 테이블 테이블 = TABLES.get (mapKey) 전에 효과를 저하시킬 것이다 (2) 후 뭔가 넣어 필요가 ... –

+0

경우에도 (2) readlock() 및 writelock 사용할 때 2) getTableLocked() 함수에서 하나의 스레드가 실행되면 해결되지 않습니다. Table table = TABLES.get (mapKey); (2)에서 쓰기 잠금은 읽기 잠금이 없으므로 (2)에서 하나의 writelock을 가져온 다음 테이블 맵을 변경하고 잠금을 해제합니다 ... (1)은 쓰기 잠금이 잠금이 아니라 테이블을 차지한다는 것을 봅니다. 인스턴스가 더 이상 거기에 쓰기 잠금에 의해 변경됩니다 .. 나는 당신이 내가 설명하려고 노력하고있어 ..)) –

+0

@ 벼랑이 뭐라고 했지. table 전에 ReadLock을 사용하십시오 – svrist

0

왜 그냥 ConcurrentHashMap을 사용하지 않는 것이 더 효율적입니다.

당신은 ConcurrentHashMap의 잠금 메커니즘을 활용하고 자신을 제거 할 수 있다고 생각합니다. 첫 번째 섹션 1 그래서 제거 :

public static void autoUnloadDbTable(final Configuration conf) { 
    final String mKey = getMapKey(conf); 
    final Table table = TABLES.remove(mKey); 
    if (table != null) { 
     table.instance.dispose(); 
    } 
} 

제 2 항은 다음과 같이이다 :

public Table getTableLocked(final Lock lock) throws FactFinderException { 
    boolean loadTable = true; 
    // Get the current table instance 
    Table table = TABLES.get(mapKey); 
       // .....(1) 
    if (table != null) { 
        //do something 
    } 

    if (loadTable) table = loadTableLocked(table); 
    return table.instance; 
} 

}

+0

알아요.하지만 사용하고 싶지는 않습니다 ...트랙에 있으십시오 .... –

+0

괜찮아요 동기화 된지도를 사용하십시오. 코드는 똑같아 보입니다. 왜 분리 된 잠금 장치를 관리해야하는지 잘 모르겠습니다. 제거 및 가져 오기는 스레드로부터 안전합니다. – richs

+0

다른 스레드가 dispose()를 호출 한 후에 테이블을 사용하여 하나의 스레드를 가질 수 있으므로 작동하지 않는다고 생각합니다. – sbridges

관련 문제