在我写的应用程序中,我需要编写很多基类型,这很可能是不可变的。但我想知道可变类型在并行应用程序中如何与不可变类型进行比较。
你可以使用带有可变对象的锁,对吗?它与并行应用程序中不可变类型使用的其他技术相比如何?
你至少不使用具有不可变类型的锁,对吗?
答案 0 :(得分:7)
类型
线程
如果必须使用显式锁定,请将它们记录下来。特别是在锁定对象的顺序方面。如果你知道Foo对象总是在Bar对象之前被锁定,并且Foo(key 100)总是在Foo(key = 200)之前被锁定,你将不会遇到死锁。
答案 1 :(得分:3)
编写可并行化应用程序的关键是远离可变共享状态。在线程之间共享可变状态需要同步,这通常需要某种形式的锁定。使用不可变类型可以帮助确保您不会意外地共享状态,因为无法更改这些对象的状态。然而,这不是一个神奇的子弹,而只是一个设计选择。如果您尝试并行化的算法需要共享状态,则必须创建某种同步。
可变性不会影响锁定。
答案 2 :(得分:1)
当您使用可变类型时,您将自己暴露于Write-After-Read或Write-After-Write错误。这些是与更新值相关的同步错误,而其他线程同时读取或更新值。
要防止同步错误,您必须使用某种形式的锁定机制。如果使用显式锁定,则需要非常小心获取锁定的顺序。如果你不小心你可以引入死锁。例如:线程A获取锁定X,然后线程B获取锁定Y.稍后,线程A请求锁定Y,线程B请求锁定X.这会导致两个线程无限期地等待永远不会释放的锁定。
锁定的两个好的经验法则:
如果您在创建对象后从不写入对象,则无需在访问对象之前将其锁定。因此,您不需要锁定不可变对象。
答案 3 :(得分:0)
尽可能使用不可变类型。必要时使用可变类型(序列化等)。
使用System.Threading.Tasks实现所有并行化 - 当添加async和await关键字时,任务甚至可以使用C#5中的语言构建。
我在C#中写了一篇关于可变/不可变类型的文章:http://rickyhelgesson.wordpress.com/2012/07/17/mutable-or-immutable-in-a-parallel-world/