Я работаю над многопоточным приложением, в котором нескольким потокам может потребоваться эксклюзивный доступ к одному и тому же файлу. Я ищу способ сериализации этих операций. Я планировал использовать блокировку flock, lockf или fcntl. Однако оказывается, что с помощью этих методов попытка заблокировать файл вторым потоком, когда первый поток уже владеет блокировкой, будет разрешена, потому что два потока находятся в одном процессе. Это согласно справочным страницам для flock и fnctl (и Я предполагаю, что в Linux lockf реализован с помощью fnctl). Также поддерживается другим вопросом. Итак, существуют ли другие способы блокировки файла в Linux, которые работают на уровне потока, а не на уровне процесса?
Некоторые альтернативы, которые я придумал, которые мне не нравятся:
1) Используйте файл блокировки (xxx.lock), открытый с помощью O_CREAT | Флаги O_EXCL. Этот вызов будет успешным только в одном потоке, если есть конфликт. Проблема в том, что тогда другие потоки должны вращаться в вызове, пока не достигнут блокировки, а это означает, что я должен _yield() или sleep(), что заставляет меня думать, что это не лучший вариант.
2) Сохраняйте список всех открытых файлов в виде мьютекса. Когда поток хочет открыть/закрыть файл, он должен сначала заблокировать список. При открытии файла он просматривает список, чтобы узнать, открыт ли он. Это звучит особенно неэффективно, потому что требует значительного объема работы, даже если файл еще не принадлежит.
Есть ли другие способы сделать это?
Редактировать: я только что обнаружил этот текст на справочных страницах моей системы, которого нет на справочных страницах в Интернете:
Если процесс использует open(2) (или аналогичный) для получения более одного дескриптора для одного и того же файла, flock() обрабатывает эти дескрипторы независимо. Попытка заблокировать файл с помощью одного из этих файловых дескрипторов может быть отклонена блокировкой, которую вызывающий процесс уже установил с помощью другого дескриптора.
Мне не нравятся слова «может быть отказано», я бы предпочел «будет отказано», но, думаю, пришло время это проверить.