1

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

ConnectionThread 负责接收数据包并解析,enque in a hash

QueueThread 负责处理Queue elelemts(hash entries)和更新DB

哈希是事件并声明为我的 %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;
}
4

2 回答 2

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)
于 2015-04-12T17:22:37.960 回答
0

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

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

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

于 2015-04-12T15:13:25.800 回答