Perl 的线程中的共享
线程是一个好东西,他不象进程占用那么多的内存,因不他不需要主空间,不需要进程控制块。他只共享所有主进程的所有内容。所以今天我们来研究一下线程的特点之一,共享的变量。
在线程中变量的基本使用的方法
如果你打算使用线程,常常会在多个子线程之间共享一些变量,常用的共享的变量可以是标量,数组,散列(hash)之类,好象 glob 和子程序不行,不过也没有必要了是吧。根据我的使用,我感觉是标量共享是直接使用,但哈希,数组只共享值的部分。
共享变量入门:
#!/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}++; } }
其实还是上一个文章的例子,这个例子本来就是为这个文章设计的,上一个例子有关 Perl 的锁,其实没有必要写成这样。从上面我们可以见到,共享变量使用的时候 lock 一下,在建一个共享的线程之间的变量是,要使用 shared 来指定.
引用的线程共享
好,上面是使用的普通的变量的共享变量,但我们能使用引用和对象来共享吗?这是我们比较关心的。我们下面就来测试一下,引用在共享变量中是否能用.
use strict; use threads; use threads::shared; my %hash : shared; my $t = threads->create(\&test); $t->join; sub test{ $hash{test}{test}++; }
输出我们发现如下:
Thread 1 terminated abnormally: Invalid value for shared scalar at threads2.pl line 10.
我们发现,我们建了一个共享的变量,%hash 时,没有问题。但我们向 $hash{test} 中放一个匿名的哈希变量时,被 threads::shared 模块检查出来,讲这个不能放入,所以导致错误。因为匿名的哈希没有声明是不能共享的。
这是我们写 Perl 程序时常用的方法,不能共享引用,怎么办啦?
use strict; use threads; use threads::shared; my %hash : shared; $hash{test} = &share({}); my $t = threads->create(\&test); $t->join; sub test{ $hash{test}{test}++; }
在这,多了一个 $hash{test} = &share({}); 我们告诉线程,我们将要放入一个共享的匿名的哈希变量来做为引用。这时就可以使用引来了。所以在这种情况我们需要先声明匿名的哈希变量来做为引用。这时如果有多级的数据结构的引用也可以,使用相同的方法就行了,象 test 下面如果还有一个 try 的话,就使用 $hash{test}{try} = &share ({});来一级一级的声明。
如果我们是一个新的 hash 需要加引用,只有一级二级,还好办,要是我们的引用是多级,多级引用下面又有多线,我们就哭了,声明共享变量都需要写很多行,这时我们可以使用 threads::shared 提供给我们的 shared_clone 功能。
例如:
$VAR1 = { ' 103班' => { '男' => [ '张三', '李四', '王五' ] }, '101班' => { '男' => [ '张三', '李四', '王五' ] }, '100班' => { '女' => [ 'A', 'B' ], '男' => [ '张三', '李四', '王五' ] } };
象上面这种,要照层次来声明是很累的。还有这个数据结构本来就存要的话,在声明也很累。所以使用 shared_clone 可以很好的解决。
use strict; use threads; use threads::shared; use Data::Dumper; my $hash_ref = shared_clone( { '100班' => { '男' => ["张三","李四", "王五"], '女' => ['A','B'] }, '101班' => { '男' => ["张三","李四", "王五"], }, ' 103班' => { '男' => ["张三","李四", "王五"], } }); my $t = threads->create(\&test); $t->join; sub test{ print Dumper $hash_ref; }
对象的线程共享
我们常常想在线程中使用同一个对象,多个线程,来操作同一个对象,这时线程中是怎么做啦?默认的对象是在线程中不共享的,也不能正常的使用的。
下面的方法,可以使用对象,在线程中,但注意,我们使用时也需要对对象进行 lock.不然会和上一个文章中讲的,线程中的锁中没锁一样,数据会乱掉.
#!/usr/bin/perl use threads; use threads::shared; my $obj = &shared_clone (FOO->new); # 要给变量声明成共享 my $th1 = threads->create(\&test1); my $th2 = threads->create(\&test2); $th1->join; $th2->join; $obj->display; sub test1 { lock ($obj); for( 1 .. 1000 ){ $obj->add_number(); } } sub test2 { lock ($obj); for( 1 .. 1000 ){ $obj->add_number(); } } package FOO; sub new { my $class = shift; my $data = { 'number' => 0 }; my $self = bless ($data, $class); return $self; } sub add_number { my $self = shift; $self->{number} ++; } sub display { my $self = shift; print $self->{number}."\n" } 1;
这其实一样是使用的 shared_clone 记的使用对象的时候,需要锁。
建议继续学习:
- 进程和线程关系及区别 (阅读:3939)
- MySQL为什么要引入Thread Pool的线程处理模式 (阅读:3501)
- 实现多线程对队列的读写操作(封装类) (阅读:3073)
- 最近几个容易错的地方总结(hash_map迭代删除,localtime(),线程状态) (阅读:3000)
- NAS解决方案实现多媒体文件共享播放 (阅读:2824)
- InnoDB线程并发检查机制 (阅读:2662)
- 检查 Linux 下线程库的类型 (阅读:2636)
- 跨平台共享鼠标键盘 (阅读:2253)
- Perl 的线程中的锁 (阅读:2113)
- Posix线程互斥编程 (阅读:2056)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:扶凯 来源: 扶凯
- 标签: 共享 线程
- 发布时间:2011-06-02 22:47:36
- [41] 界面设计速成
- [36] Oracle MTS模式下 进程地址与会话信
- [33] IOS安全–浅谈关于IOS加固的几种方法
- [33] 如何拿下简短的域名
- [32] 视觉调整-设计师 vs. 逻辑
- [32] 程序员技术练级攻略
- [32] 图书馆的世界纪录
- [31] android 开发入门
- [31] 【社会化设计】自我(self)部分――欢迎区
- [28] 读书笔记-壹百度:百度十年千倍的29条法则