在线程中创建共享变量是否可以?

时间:2010-09-29 09:17:23

标签: multithreading perl

我认为这可能是一个相当容易的问题。

我发现很多使用线程和共享变量的例子,但是在一个例子中没有在线程内创建共享变量。我想确保我不会做一些似乎有效的事情,将来会打破一些时间。

我需要这个的原因是我有一个共享哈希,它将键映射到数组引用。这些引用由一个线程创建/填充,由另一个线程读取/修改(假设正确同步)。为了存储那些数组引用,我必须让它们共享。否则我收到错误Invalid value for shared scalar

以下是一个例子:

my %hash :shared;

my $t1 = threads->create(
    sub { my @ar :shared = (1,2,3); $hash{foo} = \@ar });
$t1->join;

my $t2 = threads->create(
    sub { print Dumper(\%hash) });
$t2->join;

这可以按预期工作:第二个线程看到第一个更改。但这在所有情况下是否真的存在?


一些澄清(关于伊恩的回答):

我有一个线程从管道中读取并等待输入。如果有,线程A将在共享哈希中写入此输入(它将标量映射到哈希值......那些是需要声明共享的哈希值)并继续侦听管道。当有事情要做时,另一个线程B得到通知(通过cond_wait / cond_signal),处理共享哈希中的东西并在完成时删除相应的条目。同时A可以在哈希中添加新内容。

关于伊恩的问题

  

[...]因此,大多数人在开始任何子线程之前都会创建所有共享变量。

     

因此,即使可以在一个线程中创建共享变量,它会有多大用处?

共享哈希是一种动态增长和缩小的数据结构,表示尚未处理的计划工作。因此,在程序开始时创建完整的数据结构是没有意义的。

此外,程序必须在(至少)两个线程中,因为当然要从管道块读取。此外,如果不共享变量,我认为没有办法实现这一目标。

3 个答案:

答案 0 :(得分:3)

共享变量的原因是共享。因此,您可能希望有多个线程访问该变量。

如果在子线程中创建共享变量,在创建之前如何阻止其他线程访问它?因此,大多数人在启动任何子线程之前都会创建所有共享变量。

因此即使可以在一个线程中创建共享变量,它会有多大用处? (PS,我不知道perl中是否有任何东西阻止在线程中创建共享变量。)


PS一个好的设计将导致很少(如果有的话)共享变量

答案 1 :(得分:3)

此任务似乎非常适合核心模块Thread::Queue。您可以在启动线程之前创建队列,使用阅读器推送项目,然后使用处理线程将其弹出。您可以使用阻塞出队方法让处理线程等待输入,从而避免使用信号。

答案 2 :(得分:0)

我回答自己的问题并不好,但我认为到目前为止答案并没有真正回答。如果有更好的事情发生,我会很乐意接受。埃里克的回答虽然有所帮助。

我现在认为在线程内共享变量没有问题。原因是:Threads::Queue的{​​{1}}方法共享对其进行排队。它使用enqueue()执行此操作。由于任何线程的排队都应该是好的,所以也应该分享。