내가 예를 들어, 고유 키가있는 캐시의 어느 특정 구현을 작성해야하지만 중복 값을 포함 할 수 있습니다멀티 스레드 사용이
"/path/to/one" -> 1
"/path/to/two" -> 2
"/path/to/vienas" -> 1
"/path/to/du" -> 2
클래스는 비 차단 읽기 제공 할 필요가
/키 조회뿐만 아니라 일반적인 작성/업데이트/삭제 뮤 테이터도 제공합니다. 한 동시 쓰기가 서로의 상단에 실행하지 않는 한 - 예를 들어, 제거 값 2
은
"/path/to/one" -> 1
"/path/to/vienas" -> 1
지금까지 그렇게 성능이 문제가되지 않습니다 쓰기로 쓰기보다 중요한 것이 캐시 읽어 결과를해야한다. 전체 항목 수는 1000 개 미만이 될 수 있으므로 때때로 값을 반복하는 것이 여전히 경제적입니다. 나는
ConcurrentHashMap
또한 비 차단 내 모든 노력이 무의미 할 것이다 읽는 제공하는 것을 깨달았다 위를 기록 후
//
// tl;dr all writes are synchronized on a single lock and each
// resets the reference to the volatile immutable map after finishing
//
class CopyOnWriteCache {
private volatile Map<K, V> readOnlyMap = ImmutableMap.of();
private final Object writeLock = new Object();
public void add(CacheEntry entry) {
synchronized (writeLock) {
readOnlyMap = new ImmutableMap.Builder<K, V>()
.addAll(readOnlyMap)
.add(entry.key, entry.value)
.build();
}
}
public void remove(CacheEntry entry) {
synchronized (writeLock) {
Map<K, V> filtered = Maps.filterValues(readOnlyMap, somePredicate(entry));
readOnlyMap = ImmutableMap.copyOf(filtered);
}
}
public void update(CacheEntry entry) {
synchronized (writeLock) {
Map<K, V> filtered = Maps.filterValues(readOnlyMap, somePredicate(entry));
readOnlyMap = new ImmutableMap.Builder<K, V>()
.addAll(filtered)
.add(entry.key, entry.value)
.build();
}
}
public SomeValue lookup(K key) {
return readOnlyMap.get(key);
}
}
하지만 문이있다 :
그래서 나는이 (의사 코드) 같은 것을 썼다 눈썹 제기 자바 독 : 나는 final ConcurrentHashMap
로 volatile ImmutableMap
의 사용을 대체하고 모든 synchronized
블록을 제거한다면
iterators are designed to be used by only one thread at a time
는 동시 뮤 테이터를합니다 경쟁한다는 것이 가능하다 서로를 무효로합니까? 예를 들어, remove
에 대한 두 개의 동시 호출이 경쟁 조건으로 이어지는 방식으로 첫 번째 remove
의 결과가 완전히 무효화되는 것을 상상할 수 있습니다. 내가 볼 수
유일한 개선은있는 그대로 synchronized
를 떠나 final ConcurrentHashMap
및를 사용하여 나는 적어도 데이터의 불필요한 복사를 피할 수 있다는 것입니다.
의미가 있습니까? 아니면 여기에서 뭔가를 간과 할 수 있습니까? 누구든지이 솔루션의 다른 대안을 제안 할 수 있습니까?