2015-04-12 110 views
1

我使用Perl,以线程来处理插座信息改变Perl的哈希引用在线程

ConnectionThread 负责在哈希接收分组和解析,并且enque

QueueThread 负责处理队列elelemts(散列条目)并更新数据库

散列是事件并声明为my%Events:shared;

我传递的哈希参照线程,但是我注意到,每个线程得到一个差散列REF值

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; 
} 
+0

这是为了满足你的好奇心吗? – ikegami

回答

0

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

尽管%Eventsshared这不会在每个线程打印相同的内存地址,如果你print \%Events;

鉴于你在谈论虽然排队,可我建议,而不是使用Thread::Queue它允许你“做”队列/出列操作以一种简单且线程安全的方式。

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)