Является ли потокобезопасной реализация glibc fprintf() в fprintf()?
-
09-09-2019 - |
Вопрос
Является ли fprintf потокобезопасным? Руководство по glibc кажется, что это так, но мое приложение, которое записывает в файл, используя один вызов fprintf(), похоже, смешивает частичные записи из разных процессов.
Редактировать:Чтобы уточнить, программа, о которой идет речь, представляет собой полиция света плагин, и сервер работает с несколькими рабочими потоками.
Просматривая файл, можно заметить, что некоторые записи перемешаны.
правка 2:Похоже, проблема, которую я вижу, может быть связана с тем, что "рабочие потоки" lighttpd на самом деле являются отдельными процессами: http://redmine .lighttpd.net/wiki/lighttpd/Docs:MultiProcessor
Проблемы
Запустив 2 или более процессов на один разъем у вас будет лучше параллелизм, но будет несколько недостатки, которые вы должны знать от:
- mod_accesslog может создавать неработающие журналы доступа, поскольку один и тот же файл открывается дважды и НЕ синхронизируется.
- mod_status будет иметь n отдельные счетчики, по одному набору для каждого процесс.
- mod_rrdtool завершится ошибкой, так как он дважды получит одну и ту же временную метку.
- mod_uploadprogress не будет показывать правильный статус.
Решение
Вы путаете два понятия - запись из нескольких потоков и запись из нескольких процессов.
Внутри процесса можно гарантировать, что один вызов fprintf будет завершен до того, как следующему будет разрешен доступ к выходному буферу, но как только ваше приложение передаст этот вывод в файл, вы окажетесь во власти операционной системы.Без какого-либо механизма блокировки на основе операционной системы вы не можете гарантировать, что совершенно другое приложение не выполнит запись в ваш файл журнала.
Другие советы
Мне кажется, вам нужно читать дальше блокировка файла.Проблема, с которой вы сталкиваетесь, заключается в том, что несколько процессов (т.е.не потоки) записываются в один и тот же файл одновременно, и нет надежного способа гарантировать, что записи будут атомарными.Это может привести к перезаписи файлов при записи друг друга, смешанному выводу и в целом недетерминированному поведению.
Это не имеет никакого отношения к потокобезопасности, поскольку это актуально только в однопроцессорных многопоточных программах.
Текущий стандарт C ++ не говорит ничего полезного о параллелизме, как и стандарт C 1990 года.(Я не читал стандарт C 1999 года, поэтому не могу его комментировать;грядущий стандарт C ++ 0x действительно что-то говорит, но я не знаю точно, что именно, навскидку.)
Это означает, что fprintf() сама по себе, вероятно, не является ни потокобезопасной, ни какой-либо другой, и что это будет зависеть от реализации.Я бы прочитал, что именно говорится об этом в документации glibc, и сравнил бы это с тем, что вы делаете.