System.RegularExpressions.TRegEx 是线程安全的吗?
Is System.RegularExpressions.TRegEx thread-safe?
背景:我遇到的一个应用程序使用来自多个线程的TRegEx
单例。单例在 class 构造函数中初始化为 TRegEx.Create(Pattern, [roCompiled])
,线程从 RegEx.Match(Value).Groups
开始使用它,似乎没有使用同步机制,但是应用程序运行良好。不过,这只是 TThread.Execute
覆盖的一小部分,线程上的负载很小。所以这总是可能只是偶然起作用,因为线程不太可能在关键部分相互交叉。
想法:一方面,考虑一下,TRegEx
实例只包含一个不可变(已编译)模式并继续工作是有道理的直接输入参数,或者将此输入保留在 (TMatch
) return 值中,以便以后可能继续使用——例如 NextMatch
,这是在 TMatch
上实现的而不是 TRegEx
。和 the underlying open source PCRE library seems to be thread-safe。这一切都符合上面的场景。另一方面,我认为 TRegEx
实例通常不是线程安全的,因为例如,在 function TRegEx.Match(const Input: String): TMatch
(如上所用)中,看起来要与模式匹配的字符串是第一个在匹配之前存储到实例中。并且相同的嵌套 TPerlRegEx
实例在各种函数链中传递并保持活动状态。一个共享的 TRegEx
实例似乎需要保护免受不协调的访问,例如,一个关键部分。
就是说,我怀疑 TRegEx 不是线程安全的,但我想请教多线程和判断线程安全方面的知识的人进行确认。因此,我的问题——非常笼统并且独立于它从中演变而来的应用程序:
问题:TRegEx 是线程安全的吗?
构建 Delphi 的正则表达式 class 的 PCRE 库是线程安全的。参见
但是,Delphi 包装器 TRegex
不是线程安全的。考虑在 TPerlRegEx.Match
:
中对 pcre_exec
的调用
OffsetCount := pcre_exec(FPattern, FHints, @FSubject[0], FStop, 0, Opts, @Offsets[0],
High(Offsets));
此处 FSubject
和 Offsets
是 TPerlRegEx
的成员,因此将在使用 TPerlRegEx
的此实例的不同线程之间共享,而该实例又由TRegEx
.
的实例
为了 TRegEx
在您希望的意义上成为线程安全的(多个线程在共享编译的正则表达式上执行匹配),这些变量需要对匹配函数的每次调用都是私有的。
背景:我遇到的一个应用程序使用来自多个线程的TRegEx
单例。单例在 class 构造函数中初始化为 TRegEx.Create(Pattern, [roCompiled])
,线程从 RegEx.Match(Value).Groups
开始使用它,似乎没有使用同步机制,但是应用程序运行良好。不过,这只是 TThread.Execute
覆盖的一小部分,线程上的负载很小。所以这总是可能只是偶然起作用,因为线程不太可能在关键部分相互交叉。
想法:一方面,考虑一下,TRegEx
实例只包含一个不可变(已编译)模式并继续工作是有道理的直接输入参数,或者将此输入保留在 (TMatch
) return 值中,以便以后可能继续使用——例如 NextMatch
,这是在 TMatch
上实现的而不是 TRegEx
。和 the underlying open source PCRE library seems to be thread-safe。这一切都符合上面的场景。另一方面,我认为 TRegEx
实例通常不是线程安全的,因为例如,在 function TRegEx.Match(const Input: String): TMatch
(如上所用)中,看起来要与模式匹配的字符串是第一个在匹配之前存储到实例中。并且相同的嵌套 TPerlRegEx
实例在各种函数链中传递并保持活动状态。一个共享的 TRegEx
实例似乎需要保护免受不协调的访问,例如,一个关键部分。
就是说,我怀疑 TRegEx 不是线程安全的,但我想请教多线程和判断线程安全方面的知识的人进行确认。因此,我的问题——非常笼统并且独立于它从中演变而来的应用程序:
问题:TRegEx 是线程安全的吗?
构建 Delphi 的正则表达式 class 的 PCRE 库是线程安全的。参见
但是,Delphi 包装器 TRegex
不是线程安全的。考虑在 TPerlRegEx.Match
:
pcre_exec
的调用
OffsetCount := pcre_exec(FPattern, FHints, @FSubject[0], FStop, 0, Opts, @Offsets[0],
High(Offsets));
此处 FSubject
和 Offsets
是 TPerlRegEx
的成员,因此将在使用 TPerlRegEx
的此实例的不同线程之间共享,而该实例又由TRegEx
.
为了 TRegEx
在您希望的意义上成为线程安全的(多个线程在共享编译的正则表达式上执行匹配),这些变量需要对匹配函数的每次调用都是私有的。