Обеспечивает ли функция python fcntl.flock блокировку доступа к файлу на уровне потоков? - PullRequest
2 голосов
/ 10 октября 2010

Модуль Python fcnt предоставляет метод, называемый [flock] [1], для проверки блокировки файлов.Его описание гласит:

Выполните операцию блокировки операции с файловым дескриптором fd (файловые объекты, предоставляющие метод fileno (), также принимаются).Подробности смотрите в руководстве Unix flock (2).(В некоторых системах эта функция эмулируется с помощью fcntl ().)

При просмотре справочной страницы linux для flock, она относится только к межпроцессной блокировке, например:

Вызов flock () может блокироваться, если другой процесс удерживает несовместимую блокировку.Чтобы сделать неблокирующий запрос, включите LOCK_NB (путем ORing) с любой из вышеперечисленных операций.

Поэтому мой вопрос: будет flock () также обеспечивать поточную безопасную блокировку и блокировать несколько потоков внутритот же процесс, что и потоки из разных процессов?

[1]: http://docs.python.org/library/fcntl.html#fcntl.flockfunction эмулируется с использованием fcntl ().)

1 Ответ

4 голосов
/ 10 октября 2010

flock блокировки не заботятся о потоках - фактически, они также не заботятся о процессах.Если вы берете один и тот же файловый дескриптор в двух процессах (унаследованных через форк), любой процесс, блокирующий файл с помощью этого FD, получит блокировку для обоих процессов.Другими словами, в следующем коде оба вызова flock вернут успех: дочерний процесс блокирует файл, а затем родительский процесс получает одну и ту же блокировку, а не блокировку, потому что они оба одинаковыFD.

import fcntl, time, os

f = open("testfile", "w+")
print "Locking..."
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
print "locked"
fcntl.flock(f.fileno(), fcntl.LOCK_UN)

if os.fork() == 0:
    # We're in the child process, and we have an inherited copy of the fd.
    # Lock the file.
    print "Child process locking..."
    fcntl.flock(f.fileno(), fcntl.LOCK_EX)
    print "Child process locked..."
    time.sleep(1000)
else:
    # We're in the parent.  Give the child process a moment to lock the file.
    time.sleep(0.5)

    print "Parent process locking..."
    fcntl.flock(f.fileno(), fcntl.LOCK_EX)
    print "Parent process locked"
    time.sleep(1000)

На одном и том же токене, если вы заблокируете один и тот же файл дважды, но с разными файловыми дескрипторами, блокировки будут блокировать друг друга - независимо от того, находитесь ли вы в одном процессе илита же нить.Смотрите flock (2): If a process uses open(2) (or similar) to obtain more than one descriptor for the same file, these descriptors are treated independently by flock(). An attempt to lock the file using one of these file descriptors may be denied by a lock that the calling process has already placed via another descriptor.

Полезно помнить, что для ядра Linux процессы и потоки, по сути, одно и то же, и, как правило, они обрабатываются API-интерфейсами уровня ядра одинаково.По большей части, если системный вызов документирует поведение дочернего / родительского процесса, то же самое относится и к потокам.

Конечно, вы можете (и, вероятно, должны) проверить это поведение самостоятельно.

...