安全地更新ConcurrentHashMap和AtomicInteger [英] Updating both a ConcurrentHashMap and an AtomicInteger safely
问题描述
我必须在哈希图中存储单词及其相应的整数索引。散列图将同时更新。
例如:假设 wordList
是 {a,b,c,a ,d,e,a,d,e,b}
哈希映射将包含以下键值对
a:1
pre>
b:2
c:3
d:4
e:5
此代码如下:
public class字典{
private ConcurrentMap< String,Integer> wordToIndex;
private AtomicInteger maxIndex;
public Dictionary(int startFrom){
wordToIndex = new ConcurrentHashMap< String,Integer>();
this.maxIndex = new AtomicInteger(startFrom);
}
public void insertAndComputeIndices(List< String> words){
Integer index;
//遍历单词列表
for(String word:words){
//检查该单词是否存在于Map中
//如果它不存在,增加maxIndex并将其放在
// Map中,如果它仍然不存在
//将maxIndex设置为新插入的索引
if(!wordToIndex.containsKey(word )){
index = maxIndex.incrementAndGet();
index = wordToIndex.putIfAbsent(word,index);
if(index!= null)
maxIndex.set(index);
}
}
}
我的问题是,类是线程安全还是不是?
基本上,在这种情况下,一个原子操作应该是增加maxIndex
,然后把这个单词放在哈希映射中,如果没有。
在这种情况下有没有更好的方法来实现并发?
解决方案参见
maxIndex
递增,然后被破坏。
假设这是所有的事情发生在地图,没有删除),那么你可以尝试把这个单词放在地图中,只有成功后才递增。
整数oldIndex = wordToIndex .putIfAbsent(word,-1);
if(oldIndex == null){
wordToIndex.put(word,maxIndex.incrementAndGet());
}
(或者单个
put
,使用某种可变类型代替Integer
。)I have to store words and their corresponding integer indices in a hash map. The hash map will be updated concurrently.
For example: lets say the
wordList
is{a,b,c,a,d,e,a,d,e,b}
The the hash map will contain the following key-value pairsa:1 b:2 c:3 d:4 e:5
The code for this is as follows:
public class Dictionary { private ConcurrentMap<String, Integer> wordToIndex; private AtomicInteger maxIndex; public Dictionary( int startFrom ) { wordToIndex = new ConcurrentHashMap<String, Integer>(); this.maxIndex = new AtomicInteger(startFrom); } public void insertAndComputeIndices( List<String> words ) { Integer index; //iterate over the list of words for ( String word : words ) { // check if the word exists in the Map // if it does not exist, increment the maxIndex and put it in the // Map if it is still absent // set the maxIndex to the newly inserted index if (!wordToIndex.containsKey(word)) { index = maxIndex.incrementAndGet(); index = wordToIndex.putIfAbsent(word, index); if (index != null) maxIndex.set(index); } } }
My question is whether the above class is thread safe or not? Basically an atomic operation in this case should be to increment the
maxIndex
and then put the word in the hash map if it is absent.Is there a better way to achieve concurrency in this situation?
解决方案Clearly another thread can see
maxIndex
incrementing and then getting clobbered.Assuming this is all that is going on to the map (in particular, no removes), then you could try putting the word in the map and only incrementing if that succeeds.
Integer oldIndex = wordToIndex.putIfAbsent(word, -1); if (oldIndex == null) { wordToIndex.put(word, maxIndex.incrementAndGet()); }
(Alternatively for a single
put
, use some sort of mutable type in place ofInteger
.)这篇关于安全地更新ConcurrentHashMap和AtomicInteger的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!