Безопасность потоков - Thread safety
Эта статья может требовать уборка встретиться с Википедией стандарты качества. Конкретная проблема: начальное определение тавтологично / циркулярноЯнварь 2016) (Узнайте, как и когда удалить этот шаблон сообщения) ( |
Безопасность потоков это компьютерное программирование концепция применима к многопоточный код. Поточно-безопасный код управляет только общими структурами данных таким образом, чтобы гарантировать, что все потоки ведут себя должным образом и выполняют свои проектные спецификации без непреднамеренного взаимодействия. Существуют различные стратегии создания потоковобезопасных структур данных.[1][2]
Программа может выполнять код одновременно в нескольких потоках в общей адресное пространство где каждый из этих потоков имеет доступ практически ко всем объем памяти любого другого потока. Поточная безопасность - это свойство, которое позволяет коду работать в многопоточной среде, восстанавливая некоторые соответствия между фактическим потоком управления и текстом программы с помощью синхронизация.
Уровни безопасности потоков
Программные библиотеки может предоставить определенные гарантии безопасности потоков. Например, одновременное чтение может быть гарантировано потокобезопасным, а одновременная запись - нет. Является ли программа, использующая такую библиотеку, потокобезопасной, зависит от того, использует ли она библиотеку в соответствии с этими гарантиями.
Разные производители используют немного разную терминологию для обеспечения безопасности потоков:[3][4][5][6]
- Потокобезопасный: Реализация гарантированно свободна от условия гонки при одновременном доступе нескольких потоков.
- Условно безопасно: Разные потоки могут обращаться к разным объектам одновременно, а доступ к общим данным защищен от состояния гонки.
- Не потокобезопасный: К структурам данных нельзя обращаться одновременно для разных потоков.
Гарантии безопасности потока обычно также включают шаги по проектированию для предотвращения или ограничения риска различных форм тупиковые ситуации, а также оптимизации для максимизации одновременной производительности. Однако гарантии отсутствия тупиковых ситуаций не всегда могут быть предоставлены, поскольку тупиковые ситуации могут быть вызваны: обратные вызовы и нарушение архитектурное наслоение независимо от самой библиотеки.
Подходы к реализации
Ниже мы обсудим два класса подходов к предотвращению условия гонки для обеспечения безопасности потоков.
Первый класс подходов направлен на предотвращение совместного использования состояния и включает:
- Повторный вход
- Написание кода таким образом, чтобы он мог частично выполняться потоком, повторно выполняться тем же потоком или одновременно выполняться другим потоком и при этом правильно завершать исходное выполнение. Это требует экономии штат информация в переменных, локальных для каждого выполнения, обычно в стеке, а не в статический или Глобальный переменные или другое нелокальное состояние. Все нелокальные состояния должны быть доступны через атомарные операции, и структуры данных также должны быть реентерабельными.
- Локальное хранилище потока
- Переменные локализованы, поэтому каждый поток имеет свою собственную частную копию. Эти переменные сохраняют свои значения через подпрограмма и другие границы кода, и являются потокобезопасными, поскольку они локальны для каждого потока, даже если код, который обращается к ним, может выполняться одновременно другим потоком.
- Неизменяемые объекты
- Состояние объекта нельзя изменить после постройки. Это означает, что совместно используются только данные только для чтения и обеспечивается внутренняя безопасность потоков. Изменяемые (неконстантные) операции могут быть реализованы таким образом, что они создают новые объекты вместо изменения существующих. Такой подход характерен для функциональное программирование а также используется строка реализации на Java, C # и Python. (Увидеть Неизменяемый объект.)
Второй класс подходов связан с синхронизацией и используется в ситуациях, когда нельзя избежать общего состояния:
- Взаимное исключение
- Доступ к общим данным есть сериализованный с помощью механизмов, которые гарантируют, что только один поток читает или записывает общие данные в любое время. Включение взаимного исключения должно быть хорошо продумано, поскольку неправильное использование может привести к побочным эффектам, таким как тупиковые ситуации, живые замки, и ресурсный голод.
- Атомарные операции
- Доступ к общим данным осуществляется с помощью атомарных операций, которые не могут быть прерваны другими потоками. Обычно это требует использования специальных машинный язык инструкции, которые могут быть доступны в библиотека времени исполнения. Поскольку операции являются атомарными, общие данные всегда сохраняются в допустимом состоянии, независимо от того, как к ним обращаются другие потоки. Атомарные операции составляют основу многих механизмов блокировки потоков и используются для реализации примитивов взаимного исключения.
Примеры
В следующем фрагменте Ява код, ключевое слово Java синхронизированный делает метод поточно-ориентированным:
класс Счетчик { частный int я = 0; общественный синхронизированный пустота inc() { я++; }}
в Язык программирования C, каждый поток имеет свой стек. Однако статическая переменная не хранится в стеке; все потоки имеют к нему одновременный доступ. Если несколько потоков перекрываются при выполнении одной и той же функции, возможно, что статическая переменная может быть изменена одним потоком, в то время как другой находится на полпути к ее проверке. Этот трудно диагностируемый логическая ошибка, который большую часть времени может компилироваться и работать правильно, называется состояние гонки. Один из распространенных способов избежать этого - использовать другую общую переменную в качестве «блокировка» или «мьютекс» (от мутуал бывшийclusion).
В следующем фрагменте кода C функция является поточно-ориентированной, но не реентерабельной:
# включить int increment_counter (){ статический int счетчик = 0; статический pthread_mutex_t мьютекс = PTHREAD_MUTEX_INITIALIZER; // разрешаем только одному потоку увеличиваться за раз pthread_mutex_lock(&мьютекс); ++счетчик; // сохраняем значение перед тем, как другие потоки увеличат его дальше int результат = счетчик; pthread_mutex_unlock(&мьютекс); вернуть результат;}
В приведенном выше описании increment_counter
могут вызываться разными потоками без каких-либо проблем, поскольку мьютекс используется для синхронизации всего доступа к общему счетчик
переменная. Но если функция используется в повторно входимом обработчике прерывания и возникает второе прерывание, когда мьютекс заблокирован, вторая процедура зависнет навсегда. Поскольку обслуживание прерываний может отключить другие прерывания, может пострадать вся система.
Одна и та же функция может быть реализована как для потоковой, так и для повторной входимости с использованием lock-free атомика в C ++ 11:
# включить <атомный>int increment_counter (){ статический стандартное::атомный<int> счетчик(0); // приращение гарантированно выполняется атомарно int результат = ++счетчик; вернуть результат;}
Смотрите также
использованная литература
- ^ Керриск, Майкл (2010). Интерфейс программирования Linux. Пресс без крахмала. п. 655.
- ^ «Руководство по многопоточному программированию». Корпорация Oracle. Ноябрь 2010 г.
Процедура является потокобезопасной, если процедура логически корректна при одновременном выполнении несколькими потоками.
- ^ "Реентерабельность и безопасность потоков | Qt 5.6". Qt Project. Получено 2016-04-20.
- ^ "ip :: tcp - 1.51.0". Boost.org. Получено 2013-10-16.
- ^ «Классификация безопасности потоков API». Publib.boulder.ibm.com. 1998-06-09. Получено 2013-10-16.
- ^ «Уровни безопасности интерфейса MT - Руководство по многопоточному программированию». Docs.oracle.com. 2010-11-01. Получено 2013-10-16.
внешние ссылки
- Эксперты по Java Q&A (20 апреля 1999 г.). «Поточно-ориентированный дизайн (20.04.99)». JavaWorld.com. Получено 2012-01-22.
- TutorialsDesk (30 сентября 2014 г.). «Учебное пособие по синхронизации и безопасности потоков с примерами на Java». TutorialsDesk.com. Получено 2012-01-22.
- Веннерс, Билл (1 августа 1998 г.). «Дизайн для обеспечения безопасности потоков». JavaWorld.com. Получено 2012-01-22.
- Зьюсс, Майкл (15 октября 2006 г.). «Краткое руководство по обеспечению безопасности потоков». Параллельное мышление. Получено 2012-01-22.