flock
将不会做你想跨线程。
您可以使用sysopen实现自己的锁定,如果该文件与O_EXCL|O_CREAT
一起使用时存在,则该锁定失败。
一个例子,与子进程的锁
use warnings;
use strict;
use feature 'say';
use Fcntl;
use Time::HiRes qw(sleep);
my $lock_file = ".lock.$$";
sub get_lock {
my ($file, $pid) = @_;
my $fh;
while (not sysopen $fh, $file, O_WRONLY|O_EXCL|O_CREAT) {
say "\t($$: lock-file exists ..)";
sleep 0.5;
}
say $fh $pid;
}
sub release_lock {
my ($file, $pid) = @_;
unlink $file or die "Error unliking $file: $!";
say "\t($$: released lock)";
}
my @pids;
for (1..4) {
my $pid = fork // die "Can't fork: $!";
if ($pid == 0) {
sleep rand 1;
get_lock($lock_file, $$);
say "$$, locked and processing";
sleep rand 1;
release_lock($lock_file, $$);
say "$$ completed.";
exit
}
push @pids, $pid;
}
wait for @pids;
它是锁文件名称更好地利用File::Temp但仔细阅读文档的微妙竞争。
与3个流程
3659, locked and processing
(3660: lock-file exists ..)
(3658: lock-file exists ..)
(3659: released lock)
3659 completed.
3660, locked and processing
(3658: lock-file exists ..)
(3658: lock-file exists ..)
(3660: released lock)
3660 completed.
3658, locked and processing
(3658: released lock)
3658 completed.
的O_EXCL
输出可能NFS下unsuppored:你必须有至少2.6内核和NFSv3还是会有竞争条件。如果这是一个问题,解决方法是使用link(2)
来获取锁定。请参阅man 2 open
(对于其他详细信息,因为sysopen
使用了open
系统调用)。
要锁定只有文件访问,例如
sub open_with_lock {
my ($file, $mode) = @_;
get_lock($lock_file, $$);
open my $fh, $mode, $file or die "Can't open $file: $!";
return $fh;
}
sub close_and_release {
my ($fh) = @_;
close $fh;
release_lock($lock_file, $$);
return 1;
}
这些可以被放置在模块中与get_lock
和release_lock
,一起锁定的文件名作为包全局,例如。
一个简单的测试驱动器
# use statements as above
use Path::Tiny; # only to show the file
my $lock_file = ".lock.file.access.$$";
my $file = 't_LOCK.txt';
my @pids;
for (1..4)
{
my $pid = fork // die "Can't fork: $!";
if ($pid == 0) {
sleep rand 1;
my $fh = open_with_lock($file, '>>');
say "$$ (#$_) opening $file ..";
say $fh "this is $$ (#$_)";
sleep rand 1;
close_and_release($fh);
say "$$ (#$_) closed $file.";
say '---';
exit;
}
push @pids, $pid;
}
wait for @pids;
print path($file)->slurp;
unlink $file;
与从第一实施例,并用3个叉use
语句,一个运行
(18956: "lock"-file exists ..) # print out of order
18954 (#1) opening t_LOCK.txt ...
(18955: "lock"-file exists ..)
(18956: "lock"-file exists ..)
(18955: "lock"-file exists ..)
(18954: released lock)
18954 (#1) closed t_LOCK.txt.
---
18956 (#3) opening t_LOCK.txt ...
(18955: "lock"-file exists ..)
(18956: released lock)
18956 (#3) closed t_LOCK.txt.
---
18955 (#2) opening t_LOCK.txt ...
(18955: released lock)
18955 (#2) closed t_LOCK.txt.
---
this is 18954 (#1)
this is 18956 (#3)
this is 18955 (#2)
(请注意,独立的进程正在争取STDOUT
)
哼声,'flock'应该总是让另一个线程获得一个锁,而不仅仅是“处于压力之下”。 – ikegami
如果每个线程都有自己的文件句柄,是否为真? – AndyH
https://linux.die.net/man/2/flock提供了更多细节,说明在相同的进程和相同或不同的fd内,鸡群如何以及何时能够成功。 – ulix