2015-04-12 74 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)