简体   繁体   English

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

[英]How to make objects Threadsafe on c#?

I have a an application that requires threading in most cases. 我有一个在大多数情况下需要线程的应用程序。 Most of the time I will encounter errors or wrong values because the object was updated prior to its execution for each thread. 大多数情况下,我会遇到错误或错误的值,因为对象在每个线程执行之前都已更新。

Do you have any suggestion how to make objects be thread safe and making sure that objects have the correct for each thread? 您是否有任何建议如何使对象是线程安全的并确保对象具有正确的每个线程? Should I make my variables static ? 我应该将变量static吗?

The first thing you should do is draw a Happens-Before graph of the problem you want to solve by multi-threading. 您应该做的第一件事是绘制一个您想要通过多线程解决的问题的Happens-Before图 If you can't draw your design, it's too complicated. 如果你无法绘制你的设计,那就太复杂了。

For example, this is a happens-before graph of a method which takes two arrays of ints and outputs the sum of all elements. 例如,这是一个方法的先发生的图形,它采用两个int数组并输出所有元素的总和。

在此输入图像描述

Once you have your happens-before graph it is really easy to see what has to happen before something else, but more importantly it shows you what does not have to happen before something else. 一旦你有了事先发生的图表,很容易看到在其他事情发生之前会发生什么,但更重要的是它会向你展示在其他事情发生之前不会发生的事情。

In this example, you can get the sums of both array1 and array2 at the same time. 在此示例中,您可以同时获取array1和array2的总和。 You can also get sum1 at the same time as sum2 since they don't depend on each other. 你也可以在sum2的同时获得sum1,因为它们不相互依赖。 Adding the sums to TotalSum1 can be done in either order, (but you will need to lock around the addition step since you can't do the addition at the same time as another). 将总和添加到TotalSum1可以按任意顺序完成(但是您需要锁定添加步骤,因为您不能同时执行添加操作)。

C# .net 4.0 has a lot of useful capabilities for parallel programming. C#.net 4.0具有许多用于并行编程的有用功能。

I recommend this book Parallel Programming with Microsoft .Net -- just use the bookmarks on the left to navigate it. 我推荐这本书使用Microsoft .Net进行并行编程 - 只需使用左侧的书签进行导航即可。 It covers the parallel patterns of Loops, Tasks, Aggregation, Futures, and Pipelines. 它涵盖了Loops,Tasks,Aggregation,Futures和Pipelines的并行模式。

In the example above, I would use a Task1 to get the Array1 and Task2 to get the Array2, then within both of those I would use the Aggregation patterns built into a Parallel.For loop for the array sums, I would need to use locks or an Interlocked.Add to accumalate the subTotals, then wait for the tasks to finish and return the result. 在上面的例子中,我将使用Task1来获取Array1和Task2来获取Array2,然后在这两个中我将使用内置在Parallel.For循环中的聚合模式来获取数组和,我需要使用锁或者是一个Interlocked.Add来解释subTotals,然后等待任务完成并返回结果。

Useful Patterns: 有用的模式:

  • Task 任务
  • Parallel Loops 平行循环
  • Producer/Consumer 生产者/消费者
  • Pipeline 管道
  • Worklist 工作列表
  • MapReduce MapReduce的

Useful Tools: 有用的工具:

  • Task Parallel Library 任务并行库
    • Parallel.For 的Parallel.For
    • Parallel.Foreach, Parallel.Foreach,
    • Tasks 任务
  • PLinq PLINQ
  • Concurrent DataStructures 并发DataStructures
    • ConcurrentQueue ConcurrentQueue
    • etc. 等等
  • Locking 锁定
    • 'lock' keyword 'lock'关键字
    • Monitor (same functionality as 'lock') 监控(与'锁'功能相同)
    • Semaphores 信号灯
    • Spinlocks 自旋锁
    • Read/Write locks 读/写锁
  • Hardware Atomic Operations 硬件原子操作
    • Interlocked.Increment Interlocked.Increment
    • Interlocked.Add Interlocked.Add
    • Interlocked.CompareAndSwap Interlocked.CompareAndSwap
    • Assignments to machine word length variables like int 分配机器字长变量,如int
  • Message Passing 消息传递
    • MPI MPI
    • Barriers 障碍
    • etc. 等等

Basically, understand your problem first then choose the tools/patterns to solve it. 基本上,首先要了解您的问题,然后选择工具/模式来解决它。

Look into using the lock statement for any resources that you need to make thread safe. 查看使用lock语句获取使线程安全所需的任何资源。

http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx 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;
        }
    }
}

This would be my first step. 这将是我的第一步。 Also you can look into the Monitor class. 您还可以查看Monitor类。

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

These are the two basic ways that you can protect your resources during concurrent operations. 这些是在并发操作期间可以保护资源的两种基本方法。 There are many other ways such as mutexes, sempahores, conditional read/write locks,etc. 还有许多其他方法,如互斥,sempahores,条件读/写锁等。

Start here: Synchronizing Data for Multithreading 从这里开始: 同步数据以进行多线程处理

Basically, you'll need to use a mutex . 基本上,您需要使用互斥锁 In .NET every object can act as a mutex, so you can use the lock keyword on any object to ensure mutual exclusions. 在.NET中,每个对象都可以充当互斥锁,因此您可以在任何对象上使用lock关键字来确保互斥。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM