我认为这可能是一个相当容易的问题。
我发现很多使用线程和共享变量的例子,但是在一个例子中没有在线程内创建共享变量。我想确保我不会做一些似乎有效的事情,将来会打破一些时间。
我需要这个的原因是我有一个共享哈希,它将键映射到数组引用。这些引用由一个线程创建/填充,由另一个线程读取/修改(假设正确同步)。为了存储那些数组引用,我必须让它们共享。否则我收到错误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可以在哈希中添加新内容。
关于伊恩的问题
[...]因此,大多数人在开始任何子线程之前都会创建所有共享变量。
因此,即使可以在一个线程中创建共享变量,它会有多大用处?
共享哈希是一种动态增长和缩小的数据结构,表示尚未处理的计划工作。因此,在程序开始时创建完整的数据结构是没有意义的。
此外,程序必须在(至少)两个线程中,因为当然要从管道块读取。此外,如果不共享变量,我认为没有办法实现这一目标。
答案 0 :(得分:3)
共享变量的原因是共享。因此,您可能希望有多个线程访问该变量。
如果在子线程中创建共享变量,在创建之前如何阻止其他线程访问它?因此,大多数人在启动任何子线程之前都会创建所有共享变量。
因此即使可以在一个线程中创建共享变量,它会有多大用处? (PS,我不知道perl中是否有任何东西阻止在线程中创建共享变量。)
PS一个好的设计将导致很少(如果有的话)共享变量
答案 1 :(得分:3)
此任务似乎非常适合核心模块Thread::Queue。您可以在启动线程之前创建队列,使用阅读器推送项目,然后使用处理线程将其弹出。您可以使用阻塞出队方法让处理线程等待输入,从而避免使用信号。
答案 2 :(得分:0)
我回答自己的问题并不好,但我认为到目前为止答案并没有真正回答。如果有更好的事情发生,我会很乐意接受。埃里克的回答虽然有所帮助。
我现在认为在线程内共享变量没有问题。原因是:Threads::Queue
的{{1}}方法共享对其进行排队。它使用enqueue()
执行此操作。由于任何线程的排队都应该是好的,所以也应该分享。