安全地更新ConcurrentHashMap和AtomicInteger [英] Updating both a ConcurrentHashMap and an AtomicInteger safely

查看:400
本文介绍了安全地更新ConcurrentHashMap和AtomicInteger的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须在哈希图中存储单词及其相应的整数索引。散列图将同时更新。



例如:假设 wordList {a,b,c,a ,d,e,a,d,e,b}
哈希映射将包含以下键值对

  a:1 
b:2
c:3
d:4
e:5
pre>

此代码如下:

  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 pairs

a: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 of Integer.)

这篇关于安全地更新ConcurrentHashMap和AtomicInteger的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆