2012-07-24 34 views
1

我有一个在大多数情况下需要线程的应用程序。大多数时候我会遇到错误或错误的值,因为对象在每个线程执行之前都已更新。如何在c#上创建对象线程安全?

是否有任何建议如何使对象成为线程安全的并确保对象对每个线程都有正确的?我应该让我的变量static

+3

你应该先从书本开始。一般而言,多处理是一件很难做到的事情。 – 2012-07-24 02:00:20

回答

4

使用锁语句研究您需要使线程安全的任何资源。

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; 
     } 
    } 
} 

这将是我的第一步。你也可以看看Monitor类。

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

这些都是可以并行操作过程中保护您的资源的两种基本方式。还有很多其他方法,例如互斥锁,sempahores,条件读/写锁等。

14

你应该做的第一件事是画一个之前发生图形要通过多线程来解决问题的。如果你不能画出你的设计,那就太复杂了。

例如,这是一个方法的发生之前图,该方法需要两个ints数组并输出所有元素的总和。

enter image description here

一旦你有你的之前发生图中可以很容易看到有别的事情之前发生,但更重要的是它表明你什么没有别的东西之前发生。

在这个例子中,你可以同时得到array1和array2的总和。 你也可以和sum2同时得到sum1,因为它们不相互依赖。 将总和添加到TotalSum1可以按任意顺序完成(但是由于无法与另一个同时添加,因此您需要锁定添加步骤)。

C#.net 4.0对并行编程有很多有用的功能。

我推荐这本书Parallel Programming with Microsoft .Net - 只需用左侧的书签进行导航。它涵盖了循环,任务,聚合,期货和管道的并行模式。

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

有用的模式:

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

有用的工具:

  • 任务并行库
    • 的Parallel.For
    • Parallel.Foreach,
    • 任务
  • PLINQ
  • 并发数据结构
    • ConcurrentQueue
  • 锁定
    • '锁定' 关键字
    • 监视器(相同的功能 '锁定')
    • 信号灯
    • 自旋锁
    • 读/写锁
  • 硬件原子操作
    • Interlocked.Increment
    • Interlocked.Add
    • Interlocked.CompareAndSwap
    • 分配到象int
  • 消息机器字长度的变量传递
    • MPI
    • 壁垒

基本上,先了解你的问题,然后选择工具/模式来解决它。