Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 并行应用程序的可变与不可变_C#_.net_Parallel Processing_Immutability_Mutable - Fatal编程技术网

C# 并行应用程序的可变与不可变

C# 并行应用程序的可变与不可变,c#,.net,parallel-processing,immutability,mutable,C#,.net,Parallel Processing,Immutability,Mutable,在我正在编写的应用程序中,我需要编写许多基本类型,它们很可能是不可变的。但我想知道在并行应用程序中可变类型与不可变类型相比如何 可以对可变对象使用锁,对吗?它与并行应用程序中使用的不可变类型的其他技术相比如何 您至少不再使用不可变类型的锁,对吗?类型 尽可能多地使用不可变类型 尽可能使用线程安全集合而不是显式锁 只有在没有其他合理选择时才使用可变类型 线程 尽可能多地使用线程池 当线程池不可能时,使用无止境循环 作为最后手段,手动启动和停止线程 如果必须使用显式锁,请完整记录它们。尤其是

在我正在编写的应用程序中,我需要编写许多基本类型,它们很可能是不可变的。但我想知道在并行应用程序中可变类型与不可变类型相比如何

可以对可变对象使用锁,对吗?它与并行应用程序中使用的不可变类型的其他技术相比如何

您至少不再使用不可变类型的锁,对吗?

类型

  • 尽可能多地使用不可变类型
  • 尽可能使用线程安全集合而不是显式锁
  • 只有在没有其他合理选择时才使用可变类型
线程

  • 尽可能多地使用线程池
  • 当线程池不可能时,使用无止境循环
  • 作为最后手段,手动启动和停止线程

如果必须使用显式锁,请完整记录它们。尤其是在锁定对象的顺序方面。如果您知道Foo对象总是在Bar对象之前锁定,并且Foo(key 100)总是在Foo(key=200)之前锁定,那么就不会出现死锁。

编写并行化应用程序的关键是远离可变共享状态。在线程之间共享可变状态需要同步,这通常需要某种形式的锁定。使用不可变类型有助于确保您不会意外地共享状态,因为这样就不可能更改这些对象的状态。然而,这不是一个神奇的子弹,而是一个简单的设计选择。如果试图并行化的算法需要共享状态,则必须创建某种类型的同步


易变性不影响锁定。

当您使用易变类型时,您将暴露自己在读后写或写后写错误中。这些是在其他线程同时读取或更新值时与更新值相关的同步错误

为了防止同步错误,必须使用某种形式的锁定机制。如果使用显式锁定,则需要非常小心获取锁的顺序。如果不小心,可能会导致死锁。例如:线程A获取锁X,然后线程B获取锁Y。而稍后线程A请求锁Y,线程B请求锁X。这会导致两个线程无限期地等待永远不会释放的锁

锁定有两个很好的经验法则:

  • 按特定顺序获取锁(例如,始终在获取锁Y之前获取锁X)
  • 保持锁的时间尽可能短。在需要的时候获取它们,并在使用完后立即释放它们

如果在对象创建后从未写入对象,则无需在访问它之前锁定它。因此,您将不需要锁定不可变对象。

尽可能使用不可变类型。必要时使用可变类型(序列化等)

使用System.Threading.Tasks进行所有并行化—当添加async和await关键字时,任务甚至将内置在C#5语言中


我写了一篇文章,关于C(4)中的易变/不可变类型,如果你在.NET中,考虑使用任务并行库。还有一个线程池,只是一个非常聪明的线程池。我听说.NET的ThreadPool类正在被淡化,我强烈建议观看Rich Hickey的演示:一些关于并行应用程序的不变性、身份、状态和锁定的惊人见解。