如何在c#上创建对象Threadsafe?
我有一个在大多数情况下需要线程的应用程序。 大多数情况下,我会遇到错误或错误的值,因为对象在每个线程执行之前都已更新。
您是否有任何建议如何使对象是线程安全的并确保对象具有正确的每个线程? 我应该让我的变量保持static
吗?
请考虑将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; } } }
这将是我的第一步。 您还可以查看Monitor类。
http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx
这些是在并发操作期间可以保护资源的两种基本方法。 还有许多其他方法,如互斥,sempahores,条件读/写锁等。
您应该做的第一件事是绘制要通过multithreading解决的问题的Happens-Before图 。 如果你无法绘制你的设计,那就太复杂了。
例如,这是一个方法的发生前图,它采用两个int数组并输出所有元素的总和。
一旦你有了你之前发生的事情,很容易看出在其他事情发生之前会发生什么,但更重要的是它会向你展示在其他事情之前不必发生的事情。
在此示例中,您可以同时获取array1和array2的总和。 您也可以在sum2的同时获得sum1,因为它们不相互依赖。 将总和添加到TotalSum1可以按任意顺序完成(但是您需要锁定添加步骤,因为您不能同时执行添加操作)。
C#.net 4.0具有许多用于并行编程的有用function。
我推荐这本书使用Microsoft .Net进行并行编程 – 只需使用左侧的书签进行导航即可。 它涵盖了循环,任务,聚合,期货和管道的并行模式。
在上面的例子中,我将使用Task1来获取Array1和Task2以获取Array2,然后在这两者中我将使用内置在Parallel.For循环中的聚合模式来获取数组总和,我需要使用锁或者是一个Interlocked.Add来准备subTotals,然后等待任务完成并返回结果。
有用的模式:
- 任务
- 平行循环
- 生产者/消费者
- 管道
- 工作列表
- MapReduce的
有用的工具:
- 任务并行库
- 的Parallel.For
- Parallel.Foreach,
- 任务
- PLINQ
- 并发DataStructures
- ConcurrentQueue
- 等等
- 锁定
- ‘lock’关键字
- 监控(与’锁’function相同)
- 信号灯
- 自旋锁
- 读/写锁
- 硬件primefaces操作
- Interlocked.Increment
- Interlocked.Add
- Interlocked.CompareAndSwap
- 分配机器字长变量,如int
- 消息传递
- MPI
- 障碍
- 等等
基本上,先了解您的问题然后选择工具/模式来解决它。
从这里开始: 同步数据以进行multithreading处理
基本上,您需要使用互斥锁 。 在.NET中,每个对象都可以充当互斥锁,因此您可以在任何对象上使用lock关键字来确保互斥。