我正在编写一个应用程序,其中两个进程需要更新同一个文件file.txt
。这可能会同时发生,所以我应该实现一些锁定框架。
每个流程都需要先读取所有file.txt
,然后对其进行处理,然后写出file.txt
的修改版本。所以锁定应该在第一个文件读取之前获得,并在写入之后释放。我在flock
中检查了Fcntl
,但它似乎只能锁定文件句柄,因此在第一次读取后锁定会丢失(因为我必须关闭文件,然后才能重新打开它以进行写入后)..
此外,如果一个进程已锁定该文件,而另一个进程尝试锁定该文件,则它不应该中止,而是执行某种非忙等待,直到另一个文件释放对该文件的锁定。
如何最好地实施这种锁定方案?我可以使用CPAN模块吗?
答案 0 :(得分:5)
flock
会做你需要的。请注意,这是一个协作度量,因此其他进程需要使用相同的系统,否则将无法阻止他们对文件执行他们喜欢的操作。
关于丢失文件锁定,你有两个明显的选择
每个进程都应尝试获取flock $fh, LOCK_EX
的独占锁,并等到轮到访问该文件。
你应该使用
use Fcntl qw/ :flock :seek /;
导入这些操作的相关常量。
这是第一种方法的示例,它使用单独的锁定文件来控制对只有一条包含计数的记录的数据文件的访问。请注意,必须在进程外部创建锁定文件,因为任何检查它是否存在的尝试以及如果不存在都会创建它将导致共享进程中出现竞争条件
use strict;
use warnings;
use 5.010;
use autodie;
use Fcntl qw/ :flock /;
my ($data_file, $lock_file) = qw/ data.txt lockfile.lock /;
open my $lock_fh, '<', $lock_file;
flock $lock_fh, LOCK_EX;
open my $data_fh, '<', $data_file;
chomp(my $record = <$data_fh>);
open $data_fh, '>', $data_file;
print $data_fh ++$record, "\n";
close $data_fh;
close $lock_fh;
这是第二种方法的一个例子,它做了同样的事情,但没有使用单独的锁文件而是打开数据文件读/写。与上述锁定文件必须独立于共享进程创建的方式相同,此处的数据文件必须作为单独的操作创建。锁定系统不会阻止两个进程同时创建新文件,因此无法让它们执行此操作
use strict;
use warnings;
use 5.010;
use autodie;
use Fcntl qw/ :flock :seek /;
my $data_file = 'data.txt';
open my $data_fh, '+<', $data_file;
flock $data_fh, LOCK_EX;
chomp(my $record = <$data_fh>);
seek $data_fh, 0, SEEK_SET;
truncate $data_fh, 0;
print $data_fh ++$record, "\n";
close $data_fh;