stringtranslate.com

Состояние гонки

Состояние гонки в логической схеме. Здесь t 1 и t 2 представляют задержки распространения логических элементов. Когда входное значение A меняется с низкого на высокое, схема выдает короткий всплеск длительностью (∆ t 1 + ∆ t 2 ) − ∆ t 2 = ∆ t 1 .

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

Термин «состояние гонки» уже использовался в 1954 году, например, в докторской диссертации Дэвида А. Хаффмана «Синтез последовательных коммутационных схем». [1]

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

В электронике

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

Рассмотрим, например, двухвходовой вентиль И, на который подается следующая логика: Логический сигнал на одном входе и его отрицание (¬ — это булево отрицание ) на другом входе теоретически никогда не выводят истинное значение: . Однако, если изменения в значении распространяются на второй вход дольше, чем на первый, когда изменяются с ложного на истинное, то наступит короткий период, в течение которого оба входа будут истинными, и, следовательно, выход вентиля также будет истинным. [2]

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

Критические и некритические формы

Критическое состояние гонки возникает, когда порядок изменения внутренних переменных определяет конечное состояние, в котором окажется конечный автомат .

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

Статические, динамические и существенные формы

Статическое состояние гонки возникает, когда сигнал и его дополнение объединяются.

Динамическое состояние гонки возникает, когда оно приводит к нескольким переходам, когда предполагается только один. Они возникают из-за взаимодействия между вентилями. Его можно устранить, используя не более двух уровней вентилирования.

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

Обходные пути

Методы проектирования, такие как карты Карно, побуждают проектировщиков распознавать и устранять условия гонки до того, как они вызовут проблемы. Часто для устранения некоторых видов гонок можно добавить логическую избыточность .

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

В программном обеспечении

Состояние гонки может возникнуть в программном обеспечении, когда компьютерная программа имеет несколько путей кода, которые выполняются одновременно. Если несколько путей кода занимают иное время, чем ожидалось, они могут завершиться в ином порядке, чем ожидалось, что может привести к ошибкам программного обеспечения из-за непредвиденного поведения. Гонка также может возникнуть между двумя программами, что приведет к проблемам безопасности.

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

Гонка данных — это тип состояния гонки. Гонки данных являются важными частями различных формальных моделей памяти . Модель памяти, определенная в стандартах C11 и C++11, указывает, что программа на C или C++, содержащая гонку данных, имеет неопределенное поведение . [3] [4]

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

Пример

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

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

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

Гонка данных

Не все рассматривают гонки данных как подмножество условий гонки. [5] Точное определение гонки данных зависит от используемой формальной модели параллелизма, но обычно оно относится к ситуации, когда операция памяти в одном потоке может потенциально попытаться получить доступ к ячейке памяти в то же время, когда операция памяти в другом потоке записывает данные в эту ячейку памяти, в контексте, где это опасно. Это подразумевает, что гонка данных отличается от состояния гонки, поскольку возможен недетерминизм из -за синхронизации даже в программе без гонок данных, например, в программе, в которой все доступы к памяти используют только атомарные операции .

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

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

Примеры определений гонок данных в конкретных моделях параллелизма

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

Стандарт C++ в проекте N4296 (19.11.2014) определяет гонку данных следующим образом в разделе 1.10.23 (стр. 14) [6]

Два действия потенциально одновременны, если

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

Части этого определения, относящиеся к обработчикам сигналов, являются специфическими для C++ и нетипичны для определений гонки данных .

В статье «Обнаружение гонок данных в системах со слабой памятью» [7] дается другое определение:

"две операции с памятью конфликтуют , если они обращаются к одному и тому же месту и по крайней мере одна из них является операцией записи... "Две операции с памятью, x и y, при последовательном согласованном выполнении образуют гонку 〈x,y〉, если и только если x и y конфликтуют, и они не упорядочены отношением hb1 выполнения. Гонка 〈x,y〉 является гонкой данных , если и только если по крайней мере одна из x или y является операцией данных.

Здесь у нас есть две операции с памятью, обращающиеся к одному и тому же месту, одна из которых — запись.

Отношение hb1 определено в другом месте статьи и является примером типичного отношения « происходит-раньше »; интуитивно, если мы можем доказать, что находимся в ситуации, когда одна операция памяти X гарантированно будет выполнена до завершения до начала другой операции памяти Y, то мы говорим, что «X происходит-раньше Y». Если ни «X происходит-раньше Y», ни «Y происходит-раньше X», то мы говорим, что X и Y «не упорядочены отношением hb1». Таким образом, предложение «...и они не упорядочены отношением hb1 выполнения» можно интуитивно перевести как «...и X и Y потенциально параллельны».

В статье рассматриваются опасные только те ситуации, в которых хотя бы одна из операций с памятью является «операцией с данными»; в других частях статьи также определяется класс «операций синхронизации», которые являются безопасными для потенциально одновременного использования, в отличие от «операций с данными».

Спецификация языка Java [8] дает другое определение:

Два доступа (чтения или записи) к одной и той же переменной считаются конфликтующими, если хотя бы один из доступов является записью... Когда программа содержит два конфликтующих доступа (§17.4.1), которые не упорядочены отношением «происходит раньше», говорят, что она содержит гонку данных... гонка данных не может привести к некорректному поведению, например, к возврату неправильной длины массива.

Критическое различие между подходом C++ и подходом Java заключается в том, что в C++ гонка данных является неопределенным поведением, тогда как в Java гонка данных просто влияет на «межпоточные действия». [8] Это означает, что в C++ попытка выполнить программу, содержащую гонку данных, может (при соблюдении спецификации) привести к сбою или может продемонстрировать небезопасное или странное поведение, тогда как в Java попытка выполнить программу, содержащую гонку данных, может привести к нежелательному поведению параллелизма, но в остальном (при условии, что реализация соответствует спецификации) безопасна.

Последовательная согласованность для свободы от гонки данных

Важным аспектом гонок данных является то, что в некоторых контекстах программа, свободная от гонок данных, гарантированно будет выполняться последовательно -согласованным образом, что значительно облегчает рассуждения о параллельном поведении программы. Говорят, что формальные модели памяти, которые предоставляют такую ​​гарантию, демонстрируют свойство "SC for DRF" (Sequential Consistency for Data Race Freedom). Говорят, что этот подход недавно достиг консенсуса (предположительно, по сравнению с подходами, которые гарантируют последовательную согласованность во всех случаях, или подходами, которые не гарантируют ее вообще). [9]

Например, в Java эта гарантия указана напрямую: [8]

Программа корректно синхронизирована тогда и только тогда, когда все последовательно согласованные выполнения свободны от гонок данных.

Если программа правильно синхронизирована, то все ее выполнения будут казаться последовательно согласованными (§17.4.3).

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

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

Напротив, проект спецификации C++ напрямую не требует наличия SC для свойства DRF, а просто отмечает, что существует теорема, обеспечивающая его:

[Примечание: можно показать, что программы, которые правильно используют мьютексы и операции memory_order_seq_cst для предотвращения всех гонок данных и не используют никаких других операций синхронизации, ведут себя так, как если бы операции, выполняемые их составляющими потоками, были просто перемежены, причем каждое вычисление значения объекта берется из последнего побочного эффекта на этом объекте в этом перемежении. Обычно это называется «последовательной согласованностью». Однако это применимо только к программам без гонок данных, а программы без гонок данных не могут наблюдать большинство преобразований программ, которые не изменяют семантику однопоточной программы. Фактически, большинство преобразований однопоточной программы по-прежнему разрешены, поскольку любая программа, которая ведет себя по-другому в результате, должна выполнить неопределенную операцию. — конец примечания

Обратите внимание, что проект спецификации C++ допускает возможность программ, которые являются допустимыми, но используют операции синхронизации с memory_order, отличным от memory_order_seq_cst, в этом случае результатом может быть программа, которая является правильной, но для которой не предоставляется никакой гарантии последовательной согласованности. Другими словами, в C++ некоторые правильные программы не являются последовательно согласованными. Считается, что этот подход дает программистам C++ свободу выбора более быстрого выполнения программы ценой отказа от простоты рассуждений о своей программе. [9]

Существуют различные теоремы, часто представленные в форме моделей памяти, которые обеспечивают гарантии SC для DRF в различных контекстах. Предпосылки этих теорем обычно накладывают ограничения как на модель памяти (и, следовательно, на реализацию), так и на программиста; то есть, как правило, существуют программы, которые не соответствуют предпосылкам теоремы и которые не могут быть гарантированно выполнены последовательно и согласованно.

Модель памяти DRF1 [10] обеспечивает SC для DRF и позволяет оптимизировать модели WO (слабый порядок), RCsc ( согласованность выпуска с последовательно согласованными специальными операциями), модель памяти VAX и модели памяти data-race-free-0. Модель памяти PLpc [11] обеспечивает SC для DRF и позволяет оптимизировать модели TSO (общий порядок хранения), PSO, PC ( согласованность процессора ) и RCpc ( согласованность выпуска с согласованностью процессора со специальными операциями). DRFrlx [12] предоставляет набросок теоремы SC для DRF при наличии ослабленных атомов.

Компьютерная безопасность

Многие состояния гонки программного обеспечения имеют сопутствующие последствия для компьютерной безопасности . Состояние гонки позволяет злоумышленнику, имеющему доступ к общему ресурсу, вызывать сбои в работе других субъектов, использующих этот ресурс, что приводит к таким последствиям, как отказ в обслуживании [13] и повышение привилегий . [14] [15]

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

Условия гонки также намеренно используются для создания аппаратных генераторов случайных чисел и физически неклонируемых функций . [16] [ необходима цитата ] PUF могут быть созданы путем проектирования топологий схем с идентичными путями к узлу и использования производственных вариаций для случайного определения того, какие пути будут завершены первыми. Измеряя конкретный набор результатов условий гонки каждой изготовленной схемы, можно собрать профиль для каждой схемы и сохранить его в секрете, чтобы впоследствии проверить идентичность схемы.

Файловые системы

Две или более программ могут столкнуться в своих попытках изменить или получить доступ к файловой системе, что может привести к повреждению данных или повышению привилегий. [14] Блокировка файлов обеспечивает широко используемое решение. Более громоздкое средство заключается в организации системы таким образом, что один уникальный процесс (запускающий демон или что-то подобное) имеет исключительный доступ к файлу, а все остальные процессы, которым требуется доступ к данным в этом файле, делают это только через межпроцессное взаимодействие с этим процессом. Это требует синхронизации на уровне процесса.

Другая форма состояния гонки существует в файловых системах, где не связанные между собой программы могут влиять друг на друга, внезапно используя доступные ресурсы, такие как дисковое пространство, память или циклы процессора. Программное обеспечение, не разработанное тщательно для прогнозирования и обработки этой ситуации гонки, может затем стать непредсказуемым. Такой риск может быть упущен из виду в течение длительного времени в системе, которая кажется очень надежной. Но в конечном итоге может накопиться достаточно данных или может быть добавлено достаточно другого программного обеспечения, чтобы критически дестабилизировать многие части системы. Примером этого стала почти полная потеря марсохода «Spirit» вскоре после приземления, что произошло из-за удаленных записей файлов, из-за которых библиотека файловой системы заняла все доступное пространство памяти. [17] Решение заключается в том, чтобы программное обеспечение запрашивало и резервировало все необходимые ему ресурсы перед началом выполнения задачи; если этот запрос не выполняется, то задача откладывается, избегая множества точек, где мог произойти сбой. В качестве альтернативы каждая из этих точек может быть снабжена обработкой ошибок, или успешность всей задачи может быть проверена впоследствии, перед продолжением. Более распространенный подход заключается в том, чтобы просто проверить, что доступно достаточно системных ресурсов перед началом выполнения задачи; Однако этого может быть недостаточно, поскольку в сложных системах действия других запущенных программ могут быть непредсказуемыми.

Нетворкинг

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

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

Состояние гонки может также возникнуть, когда компьютерная программа написана с использованием неблокируемых сокетов ; в этом случае производительность программы может зависеть от скорости сетевого соединения.

Системы жизнеобеспечения

Недостатки программного обеспечения в жизненно важных системах могут быть катастрофическими. Среди недостатков аппарата лучевой терапии Therac-25 были условия гонки , что привело к смерти по меньшей мере трех пациентов и травмам еще нескольких. [18]

Другим примером является система управления энергопотреблением, предоставленная GE Energy и используемая FirstEnergy Corp из Огайо (среди других энергетических объектов). В подсистеме сигнализации существовало состояние гонки; когда одновременно отключались три провисающие линии электропередач, это состояние не позволяло оповещать технических специалистов по мониторингу, задерживая их осознание проблемы. Этот программный недостаток в конечном итоге привел к отключению электроэнергии в Северной Америке в 2003 году . [19] Позднее GE Energy разработала программный патч для исправления ранее не обнаруженной ошибки.

Инструменты

Существует множество программных инструментов, помогающих обнаружить состояния гонки в программном обеспечении. Их можно в основном разделить на две группы: инструменты статического анализа и инструменты динамического анализа .

Thread Safety Analysis — это инструмент статического анализа для внутрипроцедурного статического анализа на основе аннотаций, изначально реализованный как ветвь gcc, а теперь переработанный в Clang с поддержкой PThreads. [20] [ необходим неосновной источник ]

Инструменты динамического анализа включают в себя:

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

В других областях

Нейробиология демонстрирует, что гоночные состояния могут возникать и в мозге млекопитающих. [25] [26]

В железнодорожной сигнализации Великобритании состояние гонки возникало при выполнении Правила 55. Согласно этому правилу, если поезд останавливался на движущейся линии сигналом, кочегар локомотива должен был подойти к сигнальному посту, чтобы напомнить сигнальщику о присутствии поезда. По крайней мере в одном случае, в Уинвике в 1934 году, произошел несчастный случай, потому что сигнальщик принял другой поезд до прибытия пожарного. Современная практика сигнализации устраняет состояние гонки, позволяя машинисту мгновенно связаться с сигнальным постом по радио.

Смотрите также

Ссылки

  1. ^ Хаффман, Дэвид А. «Синтез последовательных коммутационных схем» (1954).
  2. ^ Унгер, СХ (июнь 1995 г.). «Опасности, критические гонки и метастабильность». IEEE Transactions on Computers . 44 (6): 754–768. doi :10.1109/12.391185.
  3. ^ "ISO/IEC 9899:2011 - Информационные технологии - Языки программирования - C". Iso.org . Получено 2018-01-30 .
  4. ^ "ISO/IEC 14882:2011". ISO. 2 сентября 2011 г. Получено 3 сентября 2011 г.
  5. ^ Регер, Джон (2011-03-13). "Состояние гонки против гонки данных". Встроено в Academia .
  6. ^ «Рабочий проект, Стандарт языка программирования C++» (PDF) . 2014-11-19.
  7. ^ Адве, Сарита и Хилл, Марк и Миллер, Бартон и Х. Б. Нецер, Роберт. (1991). Обнаружение гонок данных в системах со слабой памятью. ACM SIGARCH Computer Architecture News. 19. 234–243. 10.1109/ISCA.1991.1021616.
  8. ^ abc "Глава 17. Потоки и блокировки". docs.oracle.com .
  9. ^ ab Adve, Sarita V.; Boehm, Hans-J. (2010). «Семантика общих переменных и синхронизация (также известная как модели памяти)» (PDF) .
  10. ^ Adve, Sarita (декабрь 1993 г.). Designing Memory Consistency Models For Shared-Memory Multiprocessors (PDF) (PhD диссертация). Архивировано (PDF) из оригинала 2021-12-09 . Получено 2021-12-09 .
  11. ^ Курош Гхарачорлоо, Сарита В. Адве, Ануп Гупта, Джон Л. Хеннесси и Марк Д. Хилл, Программирование для различных моделей согласованности памяти, Журнал параллельных и распределенных вычислений, 1992, том 15, страницы 399–407.
  12. ^ Синклер, Мэтью Дэвид (2017). "Глава 3: Эффективная поддержка и оценка расслабленных атомов" (PDF) . Эффективная когерентность и согласованность для специализированных иерархий памяти (PhD). Иллинойсский университет в Урбане-Шампейне.
  13. ^ "CVE-2015-8461: состояние гонки при обработке ошибок сокетов может привести к сбою утверждения в resolver.c". Internet Systems Consortium . Архивировано из оригинала 9 июня 2016 г. Получено 5 июня 2017 г.
  14. ^ ab "Уязвимость в rmtree() и remove_tree(): CVE-2017-6512". CPAN . Получено 5 июня 2017 г. .
  15. ^ "безопасность: кэш статистики *очень большой* состояние гонки, если кэширование при отключенном follow_symlink". lighttpd . Получено 5 июня 2017 г. .
  16. ^ Colesa, Adrian; Tudoran, Radu; Banescu, Sebastian (2008). «Программная генерация случайных чисел на основе условий гонки». 2008 10-й Международный симпозиум по символьным и числовым алгоритмам для научных вычислений . С. 439–444. doi :10.1109/synasc.2008.36. ISBN 978-0-7695-3523-4. S2CID  1586029.
  17. ^ Ривз, Гленн Э.; Нильсон, Трейси (2005). Аномалия FLASH марсохода Spirit (PDF) . 2005 IEEE Aerospace Conference. IEEE. стр. 4186–4199. doi :10.1109/aero.2005.1559723. ISBN 0-7803-8870-4. ISSN  1095-323X.
  18. ^ Левесон, Нэнси; Тернер, Кларк С. «Расследование аварий Therac-25 – I». Courses.cs.vt.edu. Архивировано из оригинала 2017-12-15.
  19. ^ Poulsen, Kevin (2004-04-07). "Отслеживание ошибки отключения электроэнергии". SecurityFocus . Получено 2011-09-19 .
  20. ^ «Анализ безопасности потоков – документация Clang 10». clang.llvm.org .
  21. ^ "ThreadSanitizer – документация Clang 10". clang.llvm.org .
  22. ^ "Helgrind: детектор ошибок потока". Valgrind .
  23. ^ «Детектор гонки данных» . Голанг .
  24. ^ "Data race benchmark suite". 25 июля 2019 г. – через GitHub.
  25. ^ "Как мозги спешат отменить ошибочные движения". Neuroskeptic . Discover Magazine. 2013-08-03. Архивировано из оригинала 2013-08-06 . Получено 2013-08-07 .
  26. ^ Шмидт, Роберт; Левенталь, Дэниел К; Маллет, Николас; Чен, Фуджун; Берке, Джошуа Д. (2013). «Отмена действий включает гонку между путями базальных ганглиев». Nature Neuroscience . 16 (8): 1118–24. doi :10.1038/nn.3456. PMC 3733500 . PMID  23852117. 

Внешние ссылки