如何使用Lazy属性和Coro防止Moose中的种族状况

时间:2017-09-04 01:07:16

标签: perl moose

我们正在开发的项目利用Coro进行异步处理,不幸的是,它太大了,不能在不久的将来离开Coro。我们遇到了竞争条件,其中具有lazy属性的对象调用构建器中的该延迟属性的构建器,线程由于某种原因而放弃,然后不同的coro线程尝试访问触发要再次构建的属性的相同属性。

通常我会保护支票然后用信号量设置代码,但是Moose的检查和设置行为是在驼鹿内部,而不是我自己的代码。

如何消除这种竞争条件?

1 个答案:

答案 0 :(得分:7)

通常,您可以从外部控制对对象或属性的访问。

my $foo_bar_lock = Coro::Semaphore->new();
my $foo = Foo->new();

{
   my $guard = $foo_bar_lock->guard;
   # ... use $foo's bar ...
}

{
   my $guard = $foo_bar_lock->guard;
   # ... use $foo's bar ...
}

但是,它也可以从内部完成。

has bar_lock => (
   reader  => '_get_bar_lock',
   default => sub { Coro::Semaphore->new() },
);

has bar => (
   reader  => '_get_bar',
   writer  => '_set_bar',
   builder => '_build_bar',
   lazy    => 1,
);

sub _build_bar { ... }

sub get_bar { 
   my $self = shift;
   my $guard = $self->_get_bar_lock->guard;
   return $self->_get_bar();
} 

sub set_bar { 
   my $self = shift;
   my $guard = $self->_get_bar_lock->guard;
   return $self->_set_bar(@_);
} 

(如果您更喜欢单个get-set访问器而不是单独的get和set访问器,请使用accessor代替readerwriter。)