【问题标题】:Is it necessary use thread-safe methods when i use AsParallel?当我使用 AsParallel 时是否有必要使用线程安全的方法?
【发布时间】:2019-09-12 16:29:38
【问题描述】:

当我使用AsParallel() 时,下一个操作在多线程中运行,所以我在此查询中使用的方法应该是线程安全的吗?

在下一个示例中,Convert(string value) 方法不是线程安全的,但正在以AsParallel() 运行的Select() 中使用。

像标准Linq一样使用AsParallel()是否正确?

注意:Convert() 方法只是一个示例,但想象一个更复杂的方法,当它在多线程环境中执行时,它确实需要线程安全的实现。

List<string> myNamesList = new List<string>()
{
   //Initialize with a lots of elements
}

List<string> myConvertedNameList = myNamesList.AsParallel()
                                               .Where("Any Condition")
                                               .Select(x => Convert(x)) 
                                               .ToList();
public string Convert(string value)
{
    int length = value.Length;
    string myFantasticValueConverted = "_" + value + "["+ length +"]";
    return myFantasticValueConverted;
}

【问题讨论】:

  • 您发布的Convert 方法是线程安全的。
  • 使用 System.Collections.Concurrent.ConcurrentBag 而不是 List
  • 并发和锁定是多线程编程中最难做好的事情。弄错可能会损害性能,甚至导致计算不正确。但是,当您使用并行 LINQ 查询数据集时,不要忘记执行查询的最佳位置,这一点很重要。您可以通过并行化加速应用程序中的查询,但查询发生的最佳位置可能仍然是在数据库中,这可以更快。因此,这可能会引入一种不同的方式来解决您试图解决的性能问题。
  • @oetzi - 这根本没有帮助。

标签: c# linq


【解决方案1】:

使用 AsParallel 时是否需要使用线程安全的方法?

是的。

【讨论】:

  • @EricJ。 docs.microsoft.com/en-us/dotnet/standard/parallel-programming/… 明确声明 ToArrayToList 很好。
  • @Brian: 没错,但让我们明确一点:ToArrayToList 在将并行处理的结果转换为数组或列表时很好 >。但是它们很好在并行进程本身中使用在不是线程安全的多个线程上枚举的接收器上时。上下文很重要。
  • 我删除了我的原始评论,因为我误解了评论者建议使用ConcurrentBag&lt;T&gt; 的位置。事实证明,他建议使用它作为源。我相信这也是不必要的,因为List&lt;T&gt; 在读取(但不更改)操作方面是线程安全的。
  • @EricJ.:没错;如果所有线程都在读取并且没有线程在写入,那么在多个线程上使用列表是安全的。请注意,这不一定适用于所有集合!例如,假设我们使用带有链接的标准散列实现一个散列集。一个合理的优化是检测是否存在被频繁读取的长链,如果是,则将被读取的元素 most 移动到列表的头部。这会在读取时改变数据结构的内部结构,因此这可能导致只读操作不是线程安全的。
  • 虽然 Eric Lippert 的警告有效,但值得注意的是所有 System.Collections.Generic 集合对于并发读取都是安全的。见docs.microsoft.com/en-us/dotnet/standard/collections/…
猜你喜欢
  • 2018-12-07
  • 1970-01-01
  • 1970-01-01
  • 2010-11-06
  • 1970-01-01
  • 2012-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多