3

MSDN 对多线程环境中的 addValueFactory 进行了以下说明:

评论

如果您在不同的线程上同时调用 AddOrUpdate,则 addValueFactory 可能会被多次调用,但它的键/值对可能不会在每次调用时都添加到字典中。

对此有一个关闭的连接问题,但似乎没有做任何事情。当我阅读上面的摘录时,我猜想可能会发生以下其中一件事情:

  1. Update() 方法被连续调用,直到它成功(可能会变成在高负载下应该避免的缓慢/争用。)

  2. 更新被丢弃,应用程序认为它成功了。(腐败)

  3. 数据在变量的线程本地副本上更新,而不是在其他线程上更新。(这可能有点牵强,但由于没有记录任何可能发生的事情)

谁能解释一下这句话是什么意思?


第2部分

@Douglas 共享我修改的代码。有趣的是,每个“添加”与每个“更新”被调用了多少次。输出很有趣,因为只有一个返回值中有一个“添加”值。尽管 Add 被多次调用,但所有其他人都“更新”了。

我想以某种方式阻止更新方法被调用。

        ConcurrentDictionary<int, string> numbers = new ConcurrentDictionary<int, string>();
        Parallel.For(0, 30, x =>
        {
           var returned = numbers.AddOrUpdate(1,
                i =>
                {
                    Console.WriteLine("addValueFactory has been called");
                    return i.ToString() + "AAA" + x;
                },
                (i, s) =>
                {
                    Console.WriteLine("updateValueFactory has been called");
                    return i.ToString() + "u" + x;
                });

           Console.WriteLine(returned);
        });

输出

addValueFactory has been called
addValueFactory has been called
addValueFactory has been called
addValueFactory has been called
addValueFactory has been called
addValueFactory has been called
updateValueFactory has been called
addValueFactory has been called
updateValueFactory has been called
addValueFactory has been called
1u15
updateValueFactory has been called
addValueFactory has been called
1u24
updateValueFactory has been called
1u25
updateValueFactory has been called
updateValueFactory has been called
1AAA0
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u26
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u18
updateValueFactory has been called
1u19
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u21
1u20
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u22
updateValueFactory has been called
1u16
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u1
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u3
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u4
1u2
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u6
1u27
updateValueFactory has been called
updateValueFactory has been called
1u23
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u9
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u10
updateValueFactory has been called
1u12
updateValueFactory has been called
updateValueFactory has been called
1u17
1u7
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u28
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u11
updateValueFactory has been called
updateValueFactory has been called
1u8
updateValueFactory has been called
updateValueFactory has been called
1u5
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
1u29
1u13
updateValueFactory has been called
1u14
4

1 回答 1

3

在实践中,它唯一的意思是你的addValueFactory方法应该是线程安全的幂等的,这意味着如果多次(可能同时)调用相同的值,它不会给出错误的结果。

考虑以下人为设计的示例:

ConcurrentDictionary<int, string> numbers = new ConcurrentDictionary<int, string>();
Parallel.For(0, 10, x =>
{
    numbers.AddOrUpdate(1,
        i =>
        {
            Console.WriteLine("addValueFactory has been called");
            return i.ToString();
        },
        (i, s) =>
        {
            Console.WriteLine("updateValueFactory has been called");
            return i.ToString();
        });
});

如果该AddOrUpdate方法完全同步,那么您会期望输出记录一个addValueFactory调用,然后是九个updateValueFactory调用。但是,由于提到的条款,您可能会收到多个addValueFactory电话。

addValueFactory has been called
addValueFactory has been called
addValueFactory has been called
addValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called
updateValueFactory has been called

在大多数情况下,这是一种良性竞争条件,特别是因为大多数addValueFactory代表不需要更改任何状态。

于 2012-11-18T23:07:48.937 回答