Reputation: 31
I am using perl with threads to process socket info
ConnectionThread is responsible for receiving packets and parsing, and enque in a hash
QueueThread Is responsible for processing Queue elelemts (hash entries ) and update DB
The Hash is Events and declared as my %Events:shared;
I am passing a hash reference to the Threads, but i noticed that each thread is getting a difference hash ref value
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);
The output is as below
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)
below is the full code ( illustrative )
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;
}
Upvotes: 1
Views: 246
Reputation: 385915
You are not directly accessing the same variable in all threads. If you did, you'd have to explicitly guarantee mutual access to the variable every time you access it (even if just to read it) to avoid crashing the program.
Each thread (including the one in which the variable is created) gets a "proxy" to the data-containing variable. The proxy is a magical variable, meaning accessing the elements of the proxy results in getters and setters being called. These getters and setters ensure the data-containing variable is never in an inconsistent state by providing mutually exclusive access to it.
$ 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)
Upvotes: 1
Reputation: 53488
Yes, this will happen. Threads do not share memory. You can sort of fake it with shared
which allows you to have common variables - but you won't necessarily see the same hash memory locations.
Despite %Events
being shared
that's not going to print the same memory address in each thread if you print \%Events;
Given you're talking about queueing though, can I suggest instead using Thread::Queue
which allows you to 'do' queue/dequeue operations in a nice easy and thread safe manner.
Upvotes: 0