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

Perl 的线程中的锁

浏览:2012次  出处信息

    本来这个文章是要写 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}++;
    }   
}

这样输出的结果,会和没有加锁时会是一样的。

建议继续学习:

  1. 无锁消息队列    (阅读:12550)
  2. 并发编程系列之一:锁的意义    (阅读:5621)
  3. 无锁HashMap的原理与实现    (阅读:5065)
  4. MySQL锁管理(并发锁,行锁,表锁,预加锁,全局锁等等)    (阅读:4296)
  5. DYNAMO平台的独门绝技: 利用NWR模型与vector clock解决锁问题    (阅读:3786)
  6. 并行编程中的“锁”难题    (阅读:3619)
  7. 进程和线程关系及区别    (阅读:3616)
  8. MySQL为什么要引入Thread Pool的线程处理模式    (阅读:3291)
  9. MySQL 中 QueryCache 的锁模型    (阅读:3159)
  10. Linux下互斥量加锁与解锁操作的C代码实现    (阅读:3030)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1