flock
будет делать то, что вам нужно. Обратите внимание, что это мера , поэтому другим процессам необходимо будет использовать одну и ту же систему, иначе не будет ничего, что помешало бы им делать то, что им нравится с файлом.
Что касается потери блокировки на файл, у вас есть два очевидных варианта
получить блокировку на отдельный файл, который существует только для контроля доступа к основному файлу. Это, вероятно, самый удобный способ.
Открыть файл с доступом для чтения и записи с использованием режима +<
. Это позволит вам прочитать файл, а затем переписать после использования seek
и truncate
Каждый процесс должен попытаться получить монопольную блокировку с 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;
См [делать блокировки файлов оставаться при использовании открытым во второй раз?] (HTTP: //переполнение стека.com/q/29308727/176646) OP этого вопроса пытался открыть файл в режиме добавления, а затем в режиме чтения/записи, но концепция такая же. – ThisSuitIsBlackNot
данные блокировки являются консультантами в любом случае (в unix), можно ли использовать отдельный файл блокировки? – Sobrique
@Sobrique Да, отдельный файл блокировки кажется хорошей идеей. Интересно, но как реализовать это, чтобы процесс не был занят - ожидал, если файл заблокирован? –