Perl 的线程中的锁
浏览:2113次 出处信息
本来这个文章是要写 Perl 线程中的锁和共享变量的,这个是几个月前的计划,但一直没有时间,好不容易现在有点时间了,就准备了一下,但发现写一个Perl 中的锁就有非常多的内容了,所以就不写共享变量了,就下一个文章中写吧。
目前在 Linux 中线程和进程和最大分别,可能就是有共享变量就个东西了。其它的地方使用起来感觉不大,只是线程更加高效,占用更加少,但是也更加容易出问题。下面就看看 Perl 中的锁和相关的问题。
先看例子。
#!/usr/bin/perl use strict; use threads; use threads::shared; use Data::Dumper; my $val : shared; # 共享变量 my %hash : shared; # 共享数组 my @array : shared; # 共享哈希 my $t1 = threads->create(\&test1); my $t2 = threads->create(\&test2); $t1->join; # 回收 t1 的线程 $t2->join; print Dumper(\$val); print Dumper(\@array); print Dumper(\%hash); sub test1 { lock ($val); lock (@array); lock (%hash); for ( 1 .. 1000 ){ $val++; $array[0]++; $hash{test}++; } } sub test2 { lock ($val); lock (@array); lock (%hash); for ( 1 .. 1000 ){ $val++; $array[0]++; $hash{test}++; } }
输出的结果
$VAR1 = \'2000'; $VAR1 = [ '2000' ]; $VAR1 = { 'test' => '2000' };
从上面,我们可以看出,在使用共享变量是,我们一定要使用一个 lock 来锁定当前需要共享的变量,这需要一个排它性。不然很容易出问题,不锁的话,会出什么问题啦,我们来看下面的例子,出掉锁以后会怎么样。
#!/usr/bin/perl use strict; use threads; use threads::shared; use Data::Dumper; my $val : shared; # 共享变量 my %hash : shared; # 共享数组 my @array : shared; # 共享哈希 my $t1 = threads->create(\&test1); my $t2 = threads->create(\&test2); $t1->join; # 回收 t1 的线程 $t2->join; print Dumper(\$val); print Dumper(\@array); print Dumper(\%hash); sub test1 { for ( 1 .. 1000 ){ $val++; $array[0]++; $hash{test}++; } } sub test2 { for ( 1 .. 1000 ){ $val++; $array[0]++; $hash{test}++; } }
输出的结果很神奇,象这个样子
$VAR1 = \'1830'; $VAR1 = [ '1922' ]; $VAR1 = { 'test' => '1922' };
本来正常的结果是 2000 的,现在好了,都是乱的,主要是因为,当进程 test1 在使用共享变量时, test2 也同时拿到这个变量,本来每个加一起,合起来是 2000,但因为拿到相同的数字相加,所以结果就乱了。所以在使用线程时,一定要非常注意共享变量加锁。
在 Perl 中有个子函数的 lock ,也有对象的方法锁,使用的方法是
子函数的锁
sub frob : locked {
# 和以前一样
}
对象方法的锁
sub frob : locked method {
# 和以前一样
}
注意,上面的方法现在 Perl 中不可用了。但书中因为历史的原因,还写着这样的方法,我们可以使用下面的方法来测试,就知道结果了
#!/usr/bin/perl use strict; use threads; use threads::shared; use Data::Dumper; my $val : shared; # 共享变量 my %hash : shared; # 共享数组 my @array : shared; # 共享哈希 my $t1 = threads->create(\&test1); my $t2 = threads->create(\&test2); $t1->join; # 回收 t1 的线程 $t2->join; print Dumper(\$val); print Dumper(\@array); print Dumper(\%hash); sub test1 : locked { for ( 1 .. 1000 ){ $val++; $array[0]++; $hash{test}++; } } sub test2 : locked { for ( 1 .. 1000 ){ $val++; $array[0]++; $hash{test}++; } }
这样输出的结果,会和没有加锁时会是一样的。
建议继续学习:
- 无锁消息队列 (阅读:12835)
- 并发编程系列之一:锁的意义 (阅读:5919)
- 无锁HashMap的原理与实现 (阅读:5369)
- MySQL锁管理(并发锁,行锁,表锁,预加锁,全局锁等等) (阅读:4509)
- DYNAMO平台的独门绝技: 利用NWR模型与vector clock解决锁问题 (阅读:3937)
- 进程和线程关系及区别 (阅读:3939)
- 并行编程中的“锁”难题 (阅读:3768)
- MySQL为什么要引入Thread Pool的线程处理模式 (阅读:3501)
- MySQL 中 QueryCache 的锁模型 (阅读:3366)
- Linux下互斥量加锁与解锁操作的C代码实现 (阅读:3251)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
扫一扫订阅我的微信号:IT技术博客大学习
<< 前一篇:Perl 的线程中的共享
后一篇:使用 Perl 实现 HTTP 代理 >>
文章信息
- 作者:扶凯 来源: 扶凯
- 标签: 线程 锁
- 发布时间:2011-06-02 23:00:37
建议继续学习
近3天十大热文
- [40] 界面设计速成
- [35] Oracle MTS模式下 进程地址与会话信
- [32] 如何拿下简短的域名
- [32] IOS安全–浅谈关于IOS加固的几种方法
- [32] 视觉调整-设计师 vs. 逻辑
- [31] 程序员技术练级攻略
- [31] 图书馆的世界纪录
- [30] 【社会化设计】自我(self)部分――欢迎区
- [30] android 开发入门
- [27] 读书笔记-壹百度:百度十年千倍的29条法则