我们正在开发的项目利用Coro进行异步处理,不幸的是,它太大了,不能在不久的将来离开Coro。我们遇到了竞争条件,其中具有lazy属性的对象调用构建器中的该延迟属性的构建器,线程由于某种原因而放弃,然后不同的coro线程尝试访问触发要再次构建的属性的相同属性。
通常我会保护支票然后用信号量设置代码,但是Moose的检查和设置行为是在驼鹿内部,而不是我自己的代码。
如何消除这种竞争条件?
答案 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
代替reader
和writer
。)