Nano Hash - криптовалюты, майнинг, программирование

Многопоточность С++ 11: вывод на консоль

Рассмотрим функцию, которая принимает массив из 100 элементов данных и выводит их на консоль.

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

Теперь, как консоль распределяется между потоками?

Тот, который первым достигает std::cout, отображает все данные, останавливая другой поток.? или Время окна консоли распределяется между потоками? если да, то что определяет количество времени, разделяемого потоками?

18.09.2013

Ответы:


1

Нет, cout не является потокобезопасным в С++ 11. Ты должен устроить это сам.

[Если быть точным, cout сама по себе потокобезопасна, но только на время фактического времени самого вызова, а типичная строка cout << x << y << endl; будет состоять из трех разных вызовов функции-члена внутри объекта cout. Таким образом, вам не нужна защита мьютекса для самой функциональности cout, но она вам нужна, чтобы гарантировать, что «линия» вызовов cout выполняется как одно целое].

18.09.2013
  • Хм, да, это так. Весь вывод сериализуется. (Это может быть не в том порядке, в котором вы ожидаете, но программа, которая вставляет cout из нескольких потоков, не имеет неопределенного поведения) 18.09.2013
  • Правильно, так что cout << 123 << 456 << endl параллельно с cout << 321 << 654 << endl; создаст одну строку 123456, за которой следует или предшествует 321456, или они могут быть произвольно смешаны любым способом, которым они выполняются? Так как, насколько я понимаю, одна такая строка транслируется в cout.operator<<(123), cout.operator<<(456), cout.operator<<(endl); - где, возможно, каждый вызов operator<< может быть синхронизирован, но точно не вся строка кода. 18.09.2013
  • Да, вы можете получить что-то вроде 123321654\n456. Я просто возражаю против использования not threadsafe, поскольку я думаю, что это подразумевает повреждение структур данных или что-то в этом роде. 18.09.2013
  • @R.MartinhoFernandes: Да, я добавил еще один абзац, чтобы покрыть это. 18.09.2013

  • 2

    Это зависит от того, как вы получаете доступ к потоку ввода/вывода:

    § 27.2.3 Безопасность потоков [iostreams.threadsafety]

    1 Одновременный доступ к объекту потока (27.8, 27.9), объекту буфера потока (27.6) или потоку библиотеки C (27.9.2) несколькими потоками может привести к гонке данных (1.10), если не указано иное (27.4). [Примечание: Гонки данных приводят к неопределенному поведению (1.10). -конец примечания]

    2 Если один поток вызывает библиотечный вызов а, который записывает значение в поток, и в результате другой поток считывает это значение из потока через библиотечный вызов b так, что это не приводит к гонке данных, тогда запись а синхронизируется. с b читать.

    также § 27.4.1

    Параллельный доступ к синхронизированному (27.5.3.4) стандартному объекту iostream с форматированными и неформатированными функциями ввода (27.7.2.1) и вывода (27.7.3.1) или стандартного потока C несколькими потоками не должен приводить к гонке данных (1.10). [Примечание: пользователи по-прежнему должны синхронизировать одновременное использование этих объектов и потоков несколькими потоками, если они хотят избежать чередования символов. -конец примечания]

    18.09.2013
  • Вы также можете процитировать §27.4.1. 18.09.2013
  • Но является ли cout простым объектом потока или на самом деле синхронизированным объектом потока? 18.09.2013
  • @Dialecticus по умолчанию. (Вы можете переопределить это.) 18.09.2013

  • 3

    Если вы используете такую ​​функцию:

    void justam(){
       std::cout << "One " << "two ";
    }
    

    а назовешь из 2-х потоков то получится более-менее упорядоченный микс из "Одного" и "двух". Это похоже на то, что вы написали бы это в двух отдельных вызовах std::cout, и хотя вам может повезти, и 1 поток может быть запланирован для обоих выходов, вы также можете быть не таким удачливым и получить что-то вроде: "one" "one " "два один ". Поскольку другие ответы охватывают С++/стандарт и поскольку С++ более или менее зависит от ОС, а планирование потоков является задачей операционной системы, ниже приведено очень хорошее краткое описание того, как это работает:

    http://en.wikipedia.org/wiki/Scheduling_%28computing%29

    Кроме того, ознакомьтесь с этой статьей, чтобы понять 3 модели многопоточности, если вам действительно интересно, что происходит:

    http://en.wikipedia.org/wiki/Thread_%28computing%29#Models

    Эти 2 статьи дадут вам представление о том, как работает многопоточность, включая буфер вывода, который, в конце концов, является ресурсом ввода-вывода, и вместе с другими ответами должны сформировать полную картину того, что происходит и чего ожидать.

    04.10.2013

    4

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

    Как часто, Boost является естественным кандидатом на это, поддерживая потокобезопасные и непотокобезопасные регистраторы и являясь почти стандартным.

    http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/log/tutorial/sources.html

    21.12.2014
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..


    © 2024 nano-hash.ru, Nano Hash - криптовалюты, майнинг, программирование