Thanks to some help,我已经开始尝试为我的脚本启用线程安全日志记录 - 但是,我似乎没有让它正常工作:
use Fcntl ':flock';
no warnings 'redefine';
sub IO::Tee::PRINT
{
my $self = shift;
my $ret = 1;
foreach my $fh (@$self) {
flock($fh, LOCK_EX);
print "\n\t\ttestA\n"; #<-- added for testing
undef $ret unless print $fh @_;
flock($fh, LOCK_UN);
print "\t\ttestB\n"; #<-- added for testing
}
return $ret;
}
my $Info_tee = IO::Tee->new(\*STDOUT, ">$ENV{DOM}\\build.log");
当我到达脚本的线程部分时:
print $Info_tee "\n------------------------------------------------------\n";
print $Info_tee "\n\t\t*** Performing Action: \'$cmd\' on $comp ***";
我输出到STDOUT
(4个主题)是:
testA
testA
------------------------------------------------------
testB
testA
------------------------------------------------------
testB
------------------------------------------------------
testB
testA
testA
------------------------------------------------------
testB
..然后脚本锁定。我做错了什么?
修改:我已经创建了一个简单的问题示例here - 我注意到如果您从脚本中remove the queue,一切似乎都可以正常工作设计的。
答案 0 :(得分:1)
简单方法
只需在共享资源周围使用explicit mutex即可。这清晰,简洁,容易:
use threads;
use threads::shared;
my $mutex : shared; # will synchronize access to our shared IO::Tee resource
async {
...
{ lock $mutex; print $shared_resource "I did something"; }
...
}
注意,您的同步需要是互斥锁或其他一些线程构造。 flock 和朋友被设计用于进程间锁定,generally don't have desirable multithreaded semantics。
更难的方式
您似乎想要的替代方法,即重新定义或扩展IO :: Tee以支持隐式互斥锁,是不明显的,冗长的,更具挑战性的。
为什么呢? IO :: Tee对象带有状态,不适合多线程使用。 (也就是说,简单地同步PRINT / PRINTF调用可能是不够的。)每个对象实际上是两个对象tie()d在一起,一个是GLOB,一个是在该glob中插入的ARRAY。 Glob不能在perl线程下共享,并且在共享时清除arrayrefs。当然,它并不棘手,但是只需使用显式互斥锁来控制对共享资源的线程访问,工作量似乎就不成比例了。
答案 1 :(得分:0)
你一如既往地不清楚。
如果您遇到的问题是脚本锁定,则不是您发布的任何内容。
如果您发布的问题是在释放锁之后正在打印东西,那是因为您需要在释放锁之前刷新缓冲区。
STDOUT->flush();
$fh->flush();
如果问题是你得到了以下内容,那是因为你没有足够长时间保持锁定(正如你之前被告知的那样)。
------------------------------------------------------
------------------------------------------------------
*** Performing Action: 'action' on comp1 ***
*** Performing Action: 'action' on comp2 ***
答案 2 :(得分:0)
你可以避免重新发明轮子。有许多日志模块支持这种开箱即用的功能。
一个例子是Log4perl:perl: Will Log::Log4perl work in a multi-threaded environment?
此致