问题的历史
线程(threads)作为对在多任务程序中组织并发计算和并行工作资源的需求的反应而出现在Perl中。自版本5.8以来,标准化模块threads稳定地进入perl,逐渐从对ithreads的实验过渡到通用的threads::shared。
问题
第一个复杂性——Perl不原生支持线程,正如Java等语言那样。Perl中的线程通过复制每个线程的堆栈和数据来工作,这会产生开销并使得无法直接访问全局变量(除非通过threads::shared进行特殊绑定的变量)。同时,在没有明确同步的情况下,Perl不保证线程在同时写入数据时的独立性。
解决方案
为了组织线程,使用模块threads和额外的模块threads::shared以便在线程之间交换数据。确保数据的同步和完整性是开发者的责任,通常通过使用锁来实现。
代码示例:
use threads; use threads::shared; my $counter :shared = 0; sub increment { lock($counter); $counter++; } my @threads; for (1..10) { push @threads, threads->create(\&increment); } $_->join for @threads; print "Counter: $counter ";
关键特点:
是否可以在不使用threads::shared的情况下使用任何全局变量,并期待线程之间能够看到彼此的更改?
不可以。全局变量在每个线程中被单独复制。要交换——只能通过threads::shared或其他IPC(通过进程)。
在同一个Perl脚本中运行fork和threads是否允许?
不建议将fork和threads混合使用,因为这会导致不可预测的错误和不稳定的行为。Perl正式警告同时使用这些技术。
是否可以通过标准引用传递复杂的数据结构到线程之间?
不可以。Perl不会自动递归复制嵌套结构,这种尝试会导致错误或非直观的结果。为此,需要进行深度复制并使用共享资源。
开发者通过一个数组创建了一个简单的队列,同时被多个线程更新,而没有使用threads::shared。数据经常损坏,程序的工作结果不正确。
优点:
缺点:
使用threads::shared和锁,整个队列被声明为shared,同步通过锁实现。程序在高负荷下运行稳定。
优点:
缺点: