Jump to content

Безопасность резьбы

(Перенаправлено с Thread-safe )

В многопоточном компьютерном программировании функция является потокобезопасной , если она может быть вызвана или доступна одновременно нескольким потокам, не вызывая неожиданного поведения, условий гонки или повреждения данных. [1] [2] Как и в многопоточном контексте, когда программа одновременно выполняет несколько потоков в общем адресном пространстве каждого другого потока , и каждый из этих потоков имеет доступ ко всей памяти , потокобезопасные функции должны гарантировать, что все эти потоки работают правильно и соответствуют своим проектным спецификациям. без непреднамеренного взаимодействия. [3]

Существуют различные стратегии создания потокобезопасных структур данных. [3]

Уровни потокобезопасности [ править ]

Разные поставщики используют несколько разную терминологию для потокобезопасности. [4] но наиболее часто используемая терминология потокобезопасности: [2]

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

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

Библиотеки программного обеспечения могут предоставить определенные гарантии потокобезопасности. [5] Например, параллельное чтение может быть гарантированно потокобезопасным, а параллельная запись — нет. Является ли программа, использующая такую ​​библиотеку, потокобезопасной, зависит от того, использует ли она библиотеку в соответствии с этими гарантиями.

Подходы к реализации [ править ]

Ниже мы обсудим два класса подходов к предотвращению условий гонки для достижения потокобезопасности.

Первый класс подходов направлен на избежание общего состояния и включает в себя:

Повторный вход [6]
Написание кода таким образом, чтобы он мог частично выполняться потоком, выполняться тем же потоком или одновременно выполняться другим потоком и при этом правильно завершать исходное выполнение. Это требует сохранения информации о состоянии в переменных, локальных для каждого выполнения, обычно в стеке, а не в статических или глобальных переменных или другом нелокальном состоянии. Доступ ко всем нелокальным состояниям должен осуществляться посредством атомарных операций, а структуры данных также должны быть реентерабельными.
Локальное хранилище потока
Переменные локализуются таким образом, что каждый поток имеет свою собственную копию. Эти переменные сохраняют свои значения вне границ подпрограммы и другого кода и являются потокобезопасными, поскольку они локальны для каждого потока, даже если код, который обращается к ним, может выполняться одновременно другим потоком.
Неизменяемые объекты
Состояние объекта не может быть изменено после постройки. Это означает, что совместно используются только данные, доступные только для чтения, и достигается присущая потокобезопасность. Изменяемые (неконстантные) операции могут быть реализованы таким образом, что они создают новые объекты вместо изменения существующих. Этот подход характерен для функционального программирования , а также используется в строковых реализациях на Java, C# и Python. (См. Неизменяемый объект .)


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

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

Примеры [ править ]

В следующем фрагменте кода Java ключевое слово Java Synchronized делает метод потокобезопасным:

class Counter {
    private int i = 0;

    public synchronized void inc() {
        i++;
    }
}

В языке программирования C каждый поток имеет свой стек. Однако статическая переменная не сохраняется в стеке; все потоки имеют одновременный доступ к нему. Если несколько потоков перекрываются при выполнении одной и той же функции, возможно, что статическая переменная может быть изменена одним потоком, пока другой находится на полпути ее проверки. Эта трудно диагностируемая логическая ошибка , которая большую часть времени может компилироваться и работать правильно, называется состоянием гонки . Один из распространенных способов избежать этого — использовать другую общую переменную в качестве «блокировки» или «мьютекса» (от исключения взаимного ) .

В следующем фрагменте кода C функция является потокобезопасной, но не реентерабельной:

# include <pthread.h>

int increment_counter ()
{
  static int counter = 0;
  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

  // only allow one thread to increment at a time
  pthread_mutex_lock(&mutex);

  ++counter;

  // store value before any other threads increment it further
  int result = counter;

  pthread_mutex_unlock(&mutex);

  return result;
}

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

Одна и та же функция может быть реализована как потокобезопасная, так и реентерабельная, используя атомарность без блокировок в C++11 :

# include <atomic>

int increment_counter ()
{
  static std::atomic<int> counter(0);

  // increment is guaranteed to be done atomically
  int result = ++counter;

  return result;
}

См. также [ править ]

Ссылки [ править ]

  1. ^ Керриск, Майкл (2010). Программный интерфейс Linux . Пресс без крахмала . п. 699, «Глава 31: ПОТОКИ: ПОТОКОВАЯ БЕЗОПАСНОСТЬ И ХРАНЕНИЕ ПО ПОТОКАМ» {{cite book}}: CS1 maint: постскриптум ( ссылка )
  2. ^ Jump up to: Перейти обратно: а б Оракул (01.11.2010). «Oracle: потокобезопасность» . Docs.oracle.com . Проверено 16 октября 2013 г. «Процедура является потокобезопасной, если она логически корректна при одновременном выполнении несколькими потоками»; «3 уровень потокобезопасности» {{cite web}}: CS1 maint: постскриптум ( ссылка )
  3. ^ Jump up to: Перейти обратно: а б Оракул (ноябрь 2020 г.). «Руководство по многопоточному программированию: Глава 7. Безопасные и небезопасные интерфейсы» . Документы Оракл . Проверено 30 апреля 2024 г .; «Потокобезопасность» {{cite web}}: CS1 maint: постскриптум ( ссылка )
  4. ^ «Классификация потокобезопасности API» . ИБМ. 11 апреля 2023 г. Проверено 9 октября 2023 г.
  5. ^ «Уровни безопасности MT для библиотек» . Документы Оракл . Проверено 17 мая 2024 г.
  6. ^ «Реентерабельность и потокобезопасность | Qt 5.6» . Qt-проект . Проверено 20 апреля 2016 г.

Внешние ссылки [ править ]

Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: a5c1bcfe493fe6c289e22440ea986bd2__1715911740
URL1:https://arc.ask3.ru/arc/aa/a5/d2/a5c1bcfe493fe6c289e22440ea986bd2.html
Заголовок, (Title) документа по адресу, URL1:
Thread safety - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)