开发者

Can you use a ConcurrentDictionary for one-to-many mapping?

I have a mapping where each key could have multiple associated values. I thought that a ConcurrentDictionary might help me more easily code this map for use in a multithreaded environment, but the methods seem to be built around a single value. I see that AddOrUpdate() 开发者_开发技巧lets me modify the value if it already exists, but it doesn't guarantee atomicity for that operation so it seems pointless? Does anyone have a good strategy for tackling this situation?

Sorry, I guess I was being a bit vague. I'd like to have multiple values for a key, ie have an IList associated with the key. But I want to be able to add/remove values from the multi-value in a safe manner. It just looked like the AddOrUpdate + delegate method might result in things getting lost if multiple calls to it were made at the same-ish time?


I thought that AddOrUpdate was atomic, but it looks like it's not atomic with regard to the delegate. Sorry!

A reference that might help: http://blogs.msdn.com/b/pfxteam/archive/2009/11/06/9918363.aspx


It looks like both AddOrUpdate and TryUpdate will work.

edit

I may well be mistaken. If so, I don't think the documentation is clear enough to say, so let's just look at the code. Courtesy of reflector:

public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
{
    TValue local;
    TValue local3;
    if (key == null)
    {
        throw new ArgumentNullException("key");
    }
    if (addValueFactory == null)
    {
        throw new ArgumentNullException("addValueFactory");
    }
    if (updateValueFactory == null)
    {
        throw new ArgumentNullException("updateValueFactory");
    }
    do
    {
        if (!this.TryGetValue(key, out local3))
        {
            TValue local2;
            local = addValueFactory(key);
            if (!this.TryAddInternal(key, local, false, true, out local2))
            {
                continue;
            }
            return local2;
        }
        local = updateValueFactory(key, local3);
    }
    while (!this.TryUpdate(key, local, local3));
    return local;
}

Now, if the update factory took an existing list and returned a new one with an additional member, it does indeed look to me as though it will be atomic. In the event of a race condition, the loser will simply have their update factory called again. Am I mistaken?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜