Chinaunix首页 | 论坛 | 博客
  • 博客访问: 153348
  • 博文数量: 42
  • 博客积分: 972
  • 博客等级: 准尉
  • 技术积分: 382
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-17 10:59
文章分类

全部博文(42)

文章存档

2014年(2)

2013年(5)

2012年(35)

我的朋友

分类: Python/Ruby

2012-11-29 13:50:51

目前在 Linux 中线程和进程和最大分别,可能就是有共享变量就个东西了.其它的地方使用起来感觉不大,只是线程更加高效,占用更加少,但是也更加容易出问题.下面就看看 Perl 中的锁和相关的问题.
先看例子.


点击(此处)折叠或打开

  1. #!/usr/bin/perl
  2. use strict;
  3. use threads;
  4. use threads::shared;

  5. use Data::Dumper;

  6. my $val : shared; # 共享变量
  7. my %hash : shared; # 共享数组
  8. my @array : shared; # 共享哈希

  9. my $t1 = threads->create(\&test1);
  10. my $t2 = threads->create(\&test2);

  11. $t1->join; # 回收 t1 的线程
  12. $t2->join;

  13. print Dumper(\$val);
  14. print Dumper(\@array);
  15. print Dumper(\%hash);

  16. sub test1 {
  17. lock ($val); lock (@array); lock (%hash);
  18. for ( 1 .. 1000 ){
  19. $val++;
  20. $array[0]++;
  21. $hash{test}++;
  22. }
  23. }

  24. sub test2 {
  25. lock ($val); lock (@array); lock (%hash);
  26. for ( 1 .. 1000 ){
  27. $val++;
  28. $array[0]++;
  29. $hash{test}++;
  30. }
  31. }

输出的结果

1
2
3
4
5
6
7
$VAR1 = \'2000';
$VAR1 = [
          '2000'
        ];
$VAR1 = {
          'test' => '2000'
        };

从上面,我们可以看出,在使用共享变量是,我们一定要使用一个 lock 来锁定当前需要共享的变量,这需要一个排它性.不然很容易出问题,不锁的话,会出什么问题啦,我们来看下面的例子,出掉锁以后会怎么样.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/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}++;
    }
}

输出的结果很神奇,象这个样子

1
2
3
4
5
6
7
$VAR1 = \'1830';
$VAR1 = [
          '1922'
        ];
$VAR1 = {
          'test' => '1922'
        };

本来正常的结果是 2000 的,现在好了,都是乱的,主要是因为,当进程 test1 在使用共享变量时, test2 也同时拿到这个变量,本来每个加一起,合起来是 2000,但因为拿到相同的数字相加,所以结果就乱了.所以在使用线程时,一定要非常注意共享变量加锁.

在 Perl 中有个子函数的 lock ,也有对象的方法锁,使用的方法是
子函数的锁
sub frob : locked {
    # 和以前一样
}
对象方法的锁
sub frob : locked method {
     # 和以前一样
}

 

注意,上面的方法现在 Perl 中不可用了.但书中因为历史的原因,还写着这样的方法,我们可以使用下面的方法来测试,就知道结果了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/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}++;
    }  
}

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


阅读(1237) | 评论(0) | 转发(0) |
0

上一篇:Perl OOP

下一篇:Perl 进程间通信

给主人留下些什么吧!~~