如何在c#上创建对象Threadsafe?

mr.*_*r.b 2 .net c# thread-safety

我有一个在大多数情况下需要线程的应用程序.大多数情况下,我会遇到错误或错误的值,因为对象在每个线程执行之前都已更新.

您是否有任何建议如何使对象是线程安全的并确保对象具有正确的每个线程?我应该制作我的变量static吗?

Xan*_*tix 17

您应该做的第一件事是绘制一个您想要通过多线程解决的问题的Happens-Before图.如果你无法绘制你的设计,那就太复杂了.

例如,这是一个方法的先发生的图形,它采用两个int数组并输出所有元素的总和.

在此输入图像描述

一旦你有了事先发生的图表,很容易看到在其他事情发生之前会发生什么,但更重要的是它会向你展示在其他事情发生之前不会发生的事情.

在此示例中,您可以同时获取array1和array2的总和.你也可以在sum2的同时获得sum1,因为它们不相互依赖.将总和添加到TotalSum1可以按任意顺序完成(但是您需要锁定添加步骤,因为您不能同时执行添加操作).

C#.net 4.0具有许多用于并行编程的有用功能.

我推荐这本书使用Microsoft .Net进行并行编程 - 只需使用左侧的书签进行导航即可.它涵盖了Loops,Tasks,Aggregation,Futures和Pipelines的并行模式.

在上面的例子中,我将使用Task1来获取Array1和Task2来获取Array2,然后在这两个中我将使用内置在Parallel.For循环中的聚合模式来获取数组和,我需要使用锁或者是一个Interlocked.Add来解释subTotals,然后等待任务完成并返回结果.

有用的模式:

  • 任务
  • 平行循环
  • 生产者/消费者
  • 管道
  • 工作列表
  • MapReduce的

有用的工具:

  • 任务并行库
    • 的Parallel.For
    • Parallel.Foreach,
    • 任务
  • PLINQ
  • 并发DataStructures
    • ConcurrentQueue
    • 等等
  • 锁定
    • 'lock'关键字
    • 监控(与'锁'功能相同)
    • 信号灯
    • 自旋锁
    • 读/写锁
  • 硬件原子操作
    • Interlocked.Increment
    • Interlocked.Add
    • Interlocked.CompareAndSwap
    • 分配机器字长变量,如int
  • 消息传递
    • MPI
    • 障碍
    • 等等

基本上,首先要了解您的问题,然后选择工具/模式来解决它.


The*_*boy 5

查看使用lock语句获取使线程安全所需的任何资源.

http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

class Account
{
    decimal balance;
    private Object thisLock = new Object();

    public void Withdraw(decimal amount)
    {
        lock (thisLock)
        {
            if (amount > balance)
            {
                throw new Exception("Insufficient funds");
            }
            balance -= amount;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这将是我的第一步.您还可以查看Monitor类.

http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx

这些是在并发操作期间可以保护资源的两种基本方法.还有许多其他方法,如互斥,sempahores,条件读/写锁等.