对于C#中的匹配,Regex实例线程是否安全?

Arl*_*ler 28 c# regex .net-4.0

我有这个正则表达式,我正在使用Parallel.ForEach<string>.安全吗?

Regex reg = new Regex(SomeRegexStringWith2Groups);
Parallel.ForEach<string>(MyStrings.ToArray(), (str) =>
{
    foreach (Match match in reg.Matches(str)) //is this safe?
        lock (dict) if (!dict.ContainsKey(match.Groups[1].Value))
            dict.Add(match.Groups[1].Value, match.Groups[2].Value);
});
Run Code Online (Sandbox Code Playgroud)

tme*_*ser 26

Regex对象是只读的,因此是线程安全的.这是他们的回报,Match可能导致问题的对象. MSDN证实了这一点:

Regex类本身是线程安全且不可变的(只读).也就是说,可以在任何线程上创建Regex对象并在线程之间共享; 匹配方法可以从任何线程调用,永远不会改变任何全局状态.

但是,Regex返回的结果对象(Match和MatchCollection)应该在单个线程上使用.

我会担心你的Match集合是如何以可能并发的方式生成的,这可能会导致集合行为有点奇怪.一些Match实现使用延迟评估,这可能会导致该foreach循环中的一些疯狂行为.我可能会收集所有的匹配,然后在以后评估它们,既安全又能获得一致的性能.

  • 在发布的示例中,每个`Matches`均由单个线程执行和使用(在Parallel.ForEach回调中)。穿过线程的对象只有Regex和dict(这是另一个问题)。 (3认同)