История изменений
Исправление router, (текущая версия) :
-
писатели запрашивают exclusive lock
- чтобы убедиться, что никто другой не будет обращаться к файлу
- но писатель не получит свой exclusive lock, пока остальные не завершат доступ к файлу. И писатели, и читатели
-
читатели запрашивают shared lock
- несколько читателей могут работать одновременно
- но если с файлом работает писатель, то читатели будут ждать, пока тот завершит свои дела
Честно говоря, не помню что будет, если пришёл новый читатель, а писатель ЖДЁТ exclusive lock. Вроде бы новые читатели встанут в очередь за писателем
Обычно не нужно специально снимать блокировку - при закрытии файла она сама исчезает
- perl
perldoc -f lock
# можно и без него, но тогда константы
# LOCK_SH, LOCK_EX, LOCK_UN придется объявлять самим
use Fcntl;
sub write_data($$) {
my $filename = shift;
my $data = shift;
open DATAFILE, "+> $filename";
flock(DATAFILE, Fcntl::LOCK_EX); # LOCK_EX = 2
# тут писатель работает с файлом
close DATAFILE;
}
sub read_data($) {
my $filename = shift;
my $data;
if ( -f $filename ){
open DATAFILE, "$filename";
flock(DATAFILE, Fcntl::LOCK_SH); # LOCK_SH = 1
# тут читатель работает с файлом
close DATAFILE;
} else {
# нет файла. Может быть, писатели ещё не запущены
# можно выкинуть ошибку или вернуть дефолтные данные
};
return $data;
}
# можно ещё использовать неблокирующий flock
# который только проверит возможность получения lock
# и если сразу не получил - вернет ошибку
# например, если нужно запускать только одну копию программы,
## if ( flock( $lock_file, Fcntl::LOCK_EX | Fcntl::LOCK_NB ) ) {
## log_info("got lock, running...");
## } else {
## log_info("can't get lock, terminating...")
## }
- python
https://docs.python.org/3/library/fcntl.html
import fcntl
def write_data(filename, data):
with open(filename, "a") as datafile:
fcntl.flock(datafile, fcntl.LOCK_EX)
# тут писатель работает с файлом
def read_data(filename):
with open(filename, "r") as datafile:
fcntl.flock(datafile, fcntl.LOCK_SH)
# тут читатель работает с файлом
# то же самое про неблокирующую проверку lock, что и для perl
# ну и можно добавить вызов close вручную,
# чтобы не ждать, пока придёт сборщик мусора
- bash
работает через системный вызов. только если он есть (в linux есть)
man 1 flock
там хорошие примеры, добавлять вроде ничего не нужно
Исходная версия router, :
-
писатели запрашивают exclusive lock
- чтобы убедиться, что никто другой не будет обращаться к файлу
- но писатель не получит свой exclusive lock, пока остальные не завершат доступ к файлу. И писатели, и читатели
-
читатели запрашивают shared lock
- несколько читателей могут работать одновременно
- но если с файлом работает писатель, то читатели будут ждать, пока тот завершит свои дела
Честно говоря, не помню что будет, если пришёл новый читатель, а писатель ЖДЁТ exclusive lock. Вроде бы новые читатели встанут в очередь за писателем
Обычно не нужно специально снимать блокировку - при закрытии файла она сама исчезает
- perl
perldoc -f lock
# можно и без него, но тогда константы
# LOCK_SH, LOCK_EX, LOCK_UN придется объявлять самим
use Fcntl;
sub write_data($$) {
my $filename = shift;
my $data = shift;
open DATAFILE, "+> $filename";
flock(DATAFILE, Fcntl::LOCK_EX); # LOCK_EX = 2
# тут писатель работает с файлом
close DATAFILE;
}
sub read_data($) {
my $filename = shift;
my $data;
if ( -f $filename ){
open DATAFILE, "$filename";
flock(DATAFILE, Fcntl::LOCK_SH); # LOCK_SH = 1
# тут читатель работает с файлом
close DATAFILE;
} else {
# нет файла. Может быть, писатели ещё не запущены
# можно выкинуть ошибку или вернуть дефолтные данные
};
return $data;
}
# можно ещё использовать неблокирующий flock
# который только проверит возможность получения lock
# и если сразу не получил - вернет ошибку
# например, если нужно запускать только одну копию программы,
## if ( flock( $lock_file, Fcntl::LOCK_EX | Fcntl::LOCK_NB ) ) {
## log_info("got lock, running...");
## } else {
## log_info("can't get lock, terminating...")
## }
- python
https://docs.python.org/3/library/fcntl.html
import fcntl
def write_data(filename, data):
with open(filename, "a") as datafile:
fcntl.flock(store_file, fcntl.LOCK_EX)
# тут писатель работает с файлом
def read_data(filename):
with open(filename, "r") as datafile:
fcntl.flock(store_file, fcntl.LOCK_SH)
# тут читатель работает с файлом
# то же самое про неблокирующую проверку lock, что и для perl
# ну и можно добавить вызов close вручную,
# чтобы не ждать, пока придёт сборщик мусора
- bash
работает через системный вызов. только если он есть (в linux есть)
man 1 flock
там хорошие примеры, добавлять вроде ничего не нужно