设计线程安全类

Sha*_*ane 15 c# multithreading thread-safety

阅读MSDN文档时,它总是让您知道类是否是线程安全的.我的问题是你如何设计一个线程安全的类?我不是在谈论用锁定调用类我意味着我正在为Microsoft创建XXX class\object而我想说它是"线程安全"我需要做什么?

Mar*_*man 8

使类线程安全的最简单和最简单的方法是使其不可变.它的美妙之处在于你再也不用担心锁定了.

配方:readonly在C#中创建所有实例变量(final在Java中).

  • 一旦在构造函数中创建和初始化,不可变对象就无法更改.
  • 不可变对象是线程安全的.期.
  • 这与只有常量的类不同.
  • 对于系统的可变部分,您仍需要考虑并处理锁定/同步属性.这是首先编写不可变类的一个原因.

也看到这个问题.


ang*_*son 5

除了这里的其他优秀答案外,还要考虑另一个角度.

如果公共API具有不能以线程安全方式使用的多步操作,则类的内部数据结构是100%线程安全是不够的.

考虑一个已经构建的列表类,无论有多少线程在做什么,无论有多少类型的操作,列表的内部数据结构总是一致的和OK.

考虑以下代码:

if (list.Count > 0)
{
    var item = list[0];
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是在读取Count属性和通过[0]索引器读取第一个元素之间,另一个线程可能已经清除了列表的内容.

创建公共API时,通常会忘记这种类型的线程安全性.在这里,唯一的解决方案是调用代码手动锁定每种此类访问的内容,以防止代码崩溃.

解决此问题的一种方法是列表类型作者考虑典型的使用场景并为该类型添加适当的方法:

public bool TryGetFirstElement(out T element)
Run Code Online (Sandbox Code Playgroud)

然后你会有:

T element;
if (list.TryGetFirstElement(out element))
{
    ....
Run Code Online (Sandbox Code Playgroud)

据推测,TryGetFirstElement它以线程安全的方式工作,并且永远不会true在无法读取第一个元素值的同时返回.