为什么 xsub 中的静态变量不是线程安全的?

Why are static variables in an xsub not thread safe?

根据perldoc threads

Since Perl 5.8, thread programming has been available using a model called interpreter threads which provides a new Perl interpreter for each thread, and, by default, results in no data or state information being shared between threads.

上述引用中提到了哪种类型的 datastate 信息?根据 perldoc perlxs

Starting with Perl 5.8, a macro framework has been defined to allow static data to be safely stored in XS modules that will be accessed from a multi-threaded Perl.

所以在我看来静态变量在线程之间共享?但是 Perl 变量不是共享的吗? (我想弄清楚究竟什么样的数据是线程安全的,以及如何创建线程安全模块)

每个线程都有自己的解释器。这个结构[1]存储了组成perl的所有内容,包括解析器状态、正则表达式引擎状态、符号table和所有“SV” (包括标量、数组、散列、代码等)。从 Perl 副本中创建新线程会生成当前解释器的副本。

XS 代码可以安全地使用 Perl API,因为每个函数都有一个指定要使用的解释器的参数。由于宏,这通常对代码不可见,但您可能已经注意到对“THX”或 "Perl context" 的引用。只是不要将属于一个口译员的 SV 传递给另一个口译员。 (您可能听说过由此产生的 "Free to wrong pool" 错误消息。)

但是 Perl 无法为其知识或控制之外的事物提供任何保护,例如它加载的外部库的静态存储。没有制作这些副本。两个线程可以同时调用同一个C函数,所以要像写多线程C程序一样小心翼翼。

您引用的那个宏框架允许访问每个解释器的存储。它还允许库指定一个函数来调用创建新的 Perl 线程以将变量克隆到新的解释器中。


  1. 如果 Perl 是在没有 -Dusemultiplicity 的情况下构建的,则 Perl 解释器由大量全局(静态)变量组成。 MULTIPLICITY 将它们移动到结构中并向 Perl API 调用添加上下文参数。这会降低性能,但它允许一个进程有多个 Perl 解释器。因为 Perl 的线程构建需要这样做,构建线程 perl (-Dusethreads) 假定 -Dusemultiplicity.