首页 > 解决方案 > 为什么 xsub 中的静态变量不是线程安全的?

问题描述

根据perldoc threads

从 Perl 5.8 开始,线程编程可以使用一种称为解释器线程的模型,它为每个线程提供一个新的 Perl 解释器,并且默认情况下,线程之间不会共享任何数据或状态信息。

上述引用中提到了哪些类型data或信息?state根据perldoc perlxs

从 Perl 5.8 开始,定义了一个宏框架以允许静态数据安全地存储在 XS 模块中,这些模块将从多线程 Perl 访问。

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

标签: multithreadingperlxs

解决方案


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

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

但是 Perl 无法对超出其知识或控制范围的事物提供任何保护,例如它加载的外部库的静态存储。没有制作这些副本。两个线程可以同时调用同一个 C 函数,因此需要像编写多线程 C 程序一样采取预防措施。

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


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

推荐阅读