技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 其他 --> Perl 的线程中的共享

Perl 的线程中的共享

浏览:2398次  出处信息

     线程是一个好东西,他不象进程占用那么多的内存,因不他不需要主空间,不需要进程控制块。他只共享所有主进程的所有内容。所以今天我们来研究一下线程的特点之一,共享的变量。

在线程中变量的基本使用的方法

如果你打算使用线程,常常会在多个子线程之间共享一些变量,常用的共享的变量可以是标量,数组,散列(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 记的使用对象的时候,需要锁。

建议继续学习:

  1. 进程和线程关系及区别    (阅读:3939)
  2. MySQL为什么要引入Thread Pool的线程处理模式    (阅读:3501)
  3. 实现多线程对队列的读写操作(封装类)    (阅读:3073)
  4. 最近几个容易错的地方总结(hash_map迭代删除,localtime(),线程状态)    (阅读:3000)
  5. NAS解决方案实现多媒体文件共享播放    (阅读:2824)
  6. InnoDB线程并发检查机制    (阅读:2662)
  7. 检查 Linux 下线程库的类型    (阅读:2636)
  8. 跨平台共享鼠标键盘    (阅读:2253)
  9. Perl 的线程中的锁    (阅读:2113)
  10. Posix线程互斥编程    (阅读:2056)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1