在多线程应用程序中查找/避免共享数据的规则

时间:2021-06-03 21:02:49

Hy,

as we all know, developing a multithreading application is a hard thing. Especially the point when and what to lock is not so obvious IMHO. Often I'm looking at a method / class and I must ask myself, if I share some data, which can be modified by multiple threads. And when I'm not sure it ends in a lock( ) over a whole code block.

众所周知,开发多线程应用程序是一件困难的事情。尤其是锁定的时间和点什么不是那么明显恕我直言。我经常看一个方法/类,我必须问自己,如果我共享一些数据,可以通过多个线程修改。当我不确定它是否在整个代码块中的lock()结束时。

So what I like to know: Do you have suggestions for patterns / rules etc. to identify shared data? Or techniques to ensure that your code is thread-safe.

所以我想知道:您是否有关于模式/规则等的建议来识别共享数据?或者确保代码是线程安全的技术。

E.g.:

  • Static methods shouldn't modify class fields. (Unless they lock the field.)
  • 静态方法不应修改类字段。 (除非他们锁定场地。)

  • Reference type'd parameters of a method should not be passed "directly". Always pass a clone.
  • 不应“直接”传递方法的参考类型参数。始终传递克隆。

By the way:

顺便说说:

Microsoft Research is working on CHESS. A tool for finding and reproducing Heisenbugs in concurrent programs. I hope this and PLINQ will make improve development of concurrent programs.

Microsoft Research正在研究CHESS。在并发程序中查找和复制Heisenbugs的工具。我希望这和PLINQ能够改进并发程序的开发。

2 个解决方案

#1


Wherever possible, make your types immutable to start with. Then there's no need to clone. If you need to "change" the contents of an object, make the method return a new object instead - just like String.Replace etc does.

尽可能使您的类型不可变。然后就没有必要克隆了。如果您需要“更改”对象的内容,请使该方法返回一个新对象 - 就像String.Replace等一样。

This is basically the functional programming style, and it's lovely. It's unfortunate that we don't (currently) have immutable collections built into the .NET framework, althoughthere are third party ones around, including one by our own JaredPar.

这基本上是函数编程风格,它很可爱。不幸的是,我们(目前)没有内置于.NET框架中的不可变集合,其中包括第三方集合,包括我们自己的JaredPar。

#2


Encapsulating data in a class is useful when making it thread safe. You get control over how the data is accessed, and you can make the class responsible for the synchronising instead of having code all over the application trying to synchronise properly.

在使线程安全时,在类中封装数据非常有用。您可以控制数据的访问方式,并且可以让类负责同步,而不是让整个应用程序的代码都尝试正确同步。

Also, you have somewhere to put a private variable that you can use as lock identifier, so that you can avoid using the data itself as identifier for the lock. By having a private variable dedicated as lock identifier you remove one possible source of deadlocks.

此外,您可以在某处放置一个可用作锁定标识符的私有变量,以便您可以避免将数据本身用作锁定的标识符。通过将专用变量专用作锁定标识符,可以删除一个可能的死锁源。

#1


Wherever possible, make your types immutable to start with. Then there's no need to clone. If you need to "change" the contents of an object, make the method return a new object instead - just like String.Replace etc does.

尽可能使您的类型不可变。然后就没有必要克隆了。如果您需要“更改”对象的内容,请使该方法返回一个新对象 - 就像String.Replace等一样。

This is basically the functional programming style, and it's lovely. It's unfortunate that we don't (currently) have immutable collections built into the .NET framework, althoughthere are third party ones around, including one by our own JaredPar.

这基本上是函数编程风格,它很可爱。不幸的是,我们(目前)没有内置于.NET框架中的不可变集合,其中包括第三方集合,包括我们自己的JaredPar。

#2


Encapsulating data in a class is useful when making it thread safe. You get control over how the data is accessed, and you can make the class responsible for the synchronising instead of having code all over the application trying to synchronise properly.

在使线程安全时,在类中封装数据非常有用。您可以控制数据的访问方式,并且可以让类负责同步,而不是让整个应用程序的代码都尝试正确同步。

Also, you have somewhere to put a private variable that you can use as lock identifier, so that you can avoid using the data itself as identifier for the lock. By having a private variable dedicated as lock identifier you remove one possible source of deadlocks.

此外,您可以在某处放置一个可用作锁定标识符的私有变量,以便您可以避免将数据本身用作锁定的标识符。通过将专用变量专用作锁定标识符,可以删除一个可能的死锁源。