【问题标题】:C# How to use Interlocked.CompareExchangeC# 如何使用 Interlocked.CompareExchange
【发布时间】:2011-09-29 09:46:53
【问题描述】:

我的目标如下:

有一定范围的整数,我必须测试该范围内的每个整数是否随机。我想为此使用多个线程,并使用共享计数器在线程之间平均分配工作。我将计数器设置为起始值,让每个线程取一个数字,增加它,进行一些计算,然后返回一个结果。这个共享计数器必须用锁递增,否则在要测试的整数范围内会有间隙/重叠。

我不知道从哪里开始。假设我想要 12 个线程来完成这项工作,我会这样做:

for (int t = 0; t < threads; t++)
{
  Thread thr = new Thread(new ThreadStart(startThread));
}

startThread() 是我用于计算的方法。

你能帮我上路吗?我知道我必须使用 Interlocked 类,但仅此而已……

【问题讨论】:

    标签: c# multithreading interlocked locks


    【解决方案1】:

    假设您在某处有一个int 字段(最初初始化为-1)然后:

    int newVal = Interlocked.Increment(ref theField);
    

    是线程安全的增量;假设您不介意溢出 int 上限的(非常小的)风险,那么:

    int next;
    while((next = Interlocked.Increment(ref theField)) <= upperInclusive) {
       // do item with index "next"
    }
    

    但是,Parallel.For 会更方便地完成所有这些操作:

    Parallel.For(lowerInclusive, upperExclusive, i => DoWork(i));
    

    或(限制为 12 个线程):

    var options = new ParallelOptions { MaxDegreeOfParallelism  = 12 };
    Parallel.For(lowerInclusive, upperExclusive, options, i => DoWork(i));
    

    【讨论】:

    • 如果我使用 Interlock.Increment,读取相同整数的线程是否仍然存在问题?只有增量没有问题,但是读取整数进行计算会失败吗?假设整数在开始时为 100,所有线程都启动,它们都读取 100,并开始在 100 上计算东西,而不是分别为 100、101、102..
    • @Inigo - 不;每个线程都在运行相同的 while 循环;第一个线程到达 Interlocked.Increment 并获得 100,下一个线程获得 101,下一个 102,等等。Interlocked.Increment 的实现确保您永远不会得到一个狡猾的读取 - 它是完全原子的.
    • 如果我执行我的程序,我会得到完全随机的结果。pastebin.com/fy7tv38H
    猜你喜欢
    • 1970-01-01
    • 2011-10-05
    • 2010-12-07
    • 2013-08-23
    • 2015-11-14
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多