【问题标题】:Perl Hash reference is changing in threadsPerl 哈希引用在线程中发生变化
【发布时间】:2015-06-17 19:05:30
【问题描述】:

我正在使用带线程的 perl 来处理套接字信息

连接线程 负责接收数据包并解析,并在hash中入队

队列线程 负责处理Queue elelemts(hash entries)和更新DB

哈希是事件并声明为 my %Events:shared;

我将哈希引用传递给线程,但我注意到每个线程都获得了不同的哈希引用值

my $hash_ref1 = \%Events ; # referencing
print "Hash ref in main is 1 " . $hash_ref1 ."\n";
my $thr1 = threads->create(\&ConnectionThread, $hash_ref1 );
my $thr2 = threads->create(\&QueueThread, $hash_ref1);

输出如下

Hash ref in main is 1 HASH(0x825faa4)
Hash ref is ConnectionThread is HASH(0x8493544)
Thread started ..
Hash ref is Queue thread is HASH(0x852dd9c)

以下是完整代码(说明性)

use strict;
use warnings;
use Socket;
use threads;
use threads::shared;
use DBI;
my %Events:shared;

sub checkSize {
    my $size;
    $size =keys %Events;
    print "Size of Queue in Check is ***" .$size ." \n";
}

sub QueueThread {
    my ($hash_ref) = @_;
    print "Hash ref is Queue thread is " . $hash_ref ." \n";
    while (1==1) {
        sleep (5);
    }
}

sub ConnectionThread {
    my ( $hash_ref ) = @_;
    print "Hash ref is ConnectionThread is " . $hash_ref ." \n";
    while (1==1) {
        sleep(5);
    }
}

my $hash_ref1 = \%Events;
print "Hash ref in main is 1 " . $hash_ref1 ."\n";
my $thr1 = threads->create(\&ConnectionThread, $hash_ref1 );
my $thr2 = threads->create(\&QueueThread, $hash_ref1);
print "Thread started ..\n";
while (1==1) {
    sleep 10;
}

【问题讨论】:

  • 只是为了满足你的好奇心吗?

标签: multithreading perl hash hashref


【解决方案1】:

您不是在所有线程中直接访问同一个变量。如果你这样做了,你必须在每次访问变量时明确保证对变量的相互访问(即使只是为了读取它)以避免程序崩溃。

每个线程(包括创建变量的线程)都会获得一个 “代理”到包含数据的变量。代理是一个神奇的变量,这意味着访问代理的元素会导致调用 getter 和 setter。这些 getter 和 setter 通过提供对它的互斥访问来确保包含数据的变量永远不会处于不一致状态。

$ perl -Mthreads -Mthreads::shared -MDevel::Peek \
   -E'my %h :shared; ( async { Dump(%h); } )->join; Dump(%h);' 2>&1 |
      grep -P '^\S|^ {8}IV'
SV = PVHV(0x1ed5f90) at 0x1f6fd68   <-----+
        IV = 31930352               <--+  |
SV = PVHV(0x1d70af0) at 0x1d880d0   <--|--+------ Two different vars
        IV = 31930352               <--+--------- Proxying the same var (0x1e737f0)

【讨论】:

    【解决方案2】:

    是的,这会发生。线程不共享内存。你可以用shared 来伪造它,它允许你拥有公共变量——但你不一定会看到相同的哈希内存位置。

    尽管%Eventsshared,但如果您使用print \%Events;,则不会在每个线程中打印相同的内存地址

    鉴于您正在谈论排队,我可以建议您改用Thread::Queue,它允许您以一种简单且线程安全的方式“执行”队列/出队操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-20
      • 2013-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多