stdout потокобезопасен в C на Linux?

Просто разделите их и проверьте их один за другим:

if (A == 'O' && B == 'O' && C == 'O' || A == 'X' && B == 'X' && C == 'X')
    // etc
37
задан Claudiu 22 January 2009 в 03:16
поделиться

4 ответа

Это не определяется стандартом C - это зависит от Вашей реализации стандартной библиотеки C. На самом деле стандарт C даже не упоминает потоки вообще, так как определенные системы (например, встроенные системы) не имеют многопоточности.

В реализации GNU (glibc), большая часть более высокого уровня функционирует в stdio, которые имеют дело с FILE*, объекты ориентированы на многопотоковое исполнение. Те, которые не являются обычно, имеют unlocked на их имена (например, getc_unlocked(3)). Однако потокобезопасность на уровне на вызов функции: при совершении множественных вызовов к printf(3), например, каждый из тех вызовов, как гарантируют, произведет атомарно, но другие потоки могли бы распечатать вещи между вызовами к printf(). Если Вы хотите удостовериться, что последовательность вызовов ввода-вывода производится атомарно, можно окружить их парой flockfile(3)/funlockfile(3) вызовы для блокировки эти FILE дескриптор. Обратите внимание, что эти функции повторно используемы, таким образом, можно безопасно звонить printf() промежуточный их, и это не приведет к мертвой блокировке, даже думал printf(), самой звонит [1 110].

вызовы ввода-вывода низкого уровня такой как [1 111] должны быть ориентированы на многопотоковое исполнение, но я не на 100% уверен в этом - write(), превращает системный вызов в ядро для выполнения ввода-вывода. То, как точно это происходит, зависит, на каком ядре Вы используете. Это могло бы быть sysenter инструкция, или int (прерывание) инструкция относительно более старых систем. Однажды в ядре, это до ядра, чтобы удостовериться, что ввод-вывод ориентирован на многопотоковое исполнение. В тесте я просто сделал с Версией 8.11.1, write(2) Ядра Darwin, кажется, ориентирован на многопотоковое исполнение.

51
ответ дан Adam Rosenfield 22 January 2009 в 03:16
поделиться
  • 1
    попробуйте свое собственное решение и отправьте результаты – Deepend 4 June 2014 в 21:58

Они оба ориентированы на многопотоковое исполнение до такой степени, что Ваше приложение не откажет, если несколько потоков назовут их на том же дескрипторе файла. Однако без некоторой блокировки прикладного уровня, независимо от того, что записано, мог быть чередован.

13
ответ дан Dave Ray 22 January 2009 в 03:16
поделиться

Это ориентировано на многопотоковое исполнение; printf должен быть повторно используем, и Вы не вызовете странности или повреждения в Вашей программе.

Вы не можете гарантировать, что Ваш вывод от одного потока не запустит половину пути через вывод от другого потока. Если Вы заботитесь об этом, необходимо разработать собственный заблокированный выходной код для предотвращения множественного доступа.

4
ответ дан Adam Hawes 22 January 2009 в 03:16
поделиться

Назовете ли вы это "потокобезопасным", зависит от вашего определения потокобезопасности. POSIX требует, чтобы функции stdio использовали блокировку, так что ваша программа не упадет, не испортит состояния объекта FILE и т.д., если вы будете использовать printf одновременно из нескольких потоков. Однако, все операции stdio формально заданы в терминах повторяющихся вызовов fgetc и fputc, поэтому атомарность в более широком масштабе не гарантируется. То есть, если потоки 1 и 2 пытаются одновременно вывести "Hello\n" и "Goodbye\n", нет гарантии, что на выходе будет либо "Hello\nGoodbye\n", либо "Goodbye\nHello\n". С таким же успехом это может быть "Привет\nГелолодбой\n". На практике, большинство реализаций будут получать одну блокировку для всего вызова записи более высокого уровня просто потому, что это более эффективно, но ваша программа не должна так считать. Могут быть угловые случаи, когда это не делается; например, реализация может полностью отказаться от блокировки на небуферизованных потоках.

Правка: Приведенный выше текст об атомарности неверен. POSIX гарантирует, что все операции stdio атомарны, но эта гарантия скрыта в документации для flockfile: http://pubs.opengroup.org/onlinepubs/9699919799/functions/flockfile.html

Все функции, ссылающиеся на объекты ( FILE *), должны вести себя так, как будто они используют flockfile() и funlockfile() для получения прав собственности на эти объекты ( FILE *).

Вы можете сами использовать функции flockfile, ftrylockfile и funlockfile для достижения более крупных, чем один вызов функции, атомарных записей.

23
ответ дан 27 November 2019 в 02:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: