1

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;
}
Jim Davis
  • 5,241
  • 1
  • 26
  • 22

2 Answers2

1

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)
ikegami
  • 367,544
  • 15
  • 269
  • 518
0

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.

Sobrique
  • 52,974
  • 7
  • 60
  • 101