我们正在开发的项目利用Coro进行异步处理,不幸的是,它太大了,不能在不久的将来离开Coro.我们遇到了竞争条件,其中具有lazy属性的对象调用构建器中的该延迟属性的构建器,线程由于某种原因而放弃,然后不同的coro线程尝试访问触发要再次构建的属性的相同属性.
通常我会保护检查,然后用信号量设置代码,但是Moose的检查和设置行为是在moose内部,而不是我自己的代码.
我怎样才能消除这种竞争条件?
解决方法
通常,您可以从外部控制对对象或属性的访问.
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访问器,请使用访问器而不是读写器.)