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