मैं, एक कैश, जो अद्वितीय कुंजी है की कुछ हद तक एक विशिष्ट कार्यान्वयन लिखने के लिए की जरूरत है लेकिन डुप्लिकेट मान हो सकते हैं जैसे:थ्रेड उपयोग
"/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 से कम होने की संभावना है, इसलिए मूल्यों पर कभी-कभी पुनरावृत्ति करना अभी भी सस्ती है।
तो मैं इस (छद्म कोड) की तरह कुछ लिखा है:
//
// 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);
}
}
ऊपर लिखने के बाद, मुझे एहसास हुआ ConcurrentHashMap
भी प्रदान करता है कि गैर अवरुद्ध पढ़ता है जो मेरे सारे प्रयास व्यर्थ हो जाएगा, लेकिन वहाँ में एक बयान है इसके जावाडोक जो एक भौंह को जन्म देती है:
iterators are designed to be used by only one thread at a time
तो अगर मैं final ConcurrentHashMap
साथ volatile ImmutableMap
के उपयोग को बदलने और सभी synchronized
ब्लॉकों को हटाने, यह संभव है कि समवर्ती mutators प्रतिस्पर्धा जाएगा एक दूसरे को अमान्य करें? उदाहरण के लिए, मैं कल्पना कर सकता हूं कि remove
पर दो समवर्ती कॉल कैसे रेस हालत का कारण बनेंगे, जो पहले remove
के परिणामों को पूरी तरह से अमान्य कर देगा।
केवल सुधार मैं देख सकता हूँ कि final ConcurrentHashMap
और का उपयोग कर synchronized
छोड़ने के रूप में वे कर रहे हैं से मैं कम से कम डेटा का अनावश्यक नकल से बचने सकता है।
क्या यह समझ में आता है - या शायद मैं यहां कुछ दिख रहा हूं? क्या कोई इस समाधान के लिए अन्य विकल्पों का सुझाव दे सकता है?