2012-02-15 3 views
0

Если есть код, который 2 потока пытается записать на один и тот же объект одновременно, я понимаю, что он не будет генерировать ошибки времени компиляции, что является причиной того, почему отладка многопоточности программа настолько сложна. Но это приведет к ошибке/исключению во время выполнения?debug multithread program

Может ли кто-нибудь предложить хорошие методы многопоточной отладки?

Спасибо.

ответ

1

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

Способ обращения с ним в многопоточной среде безопасно использовать мьютексы и семафоры. Для мьютексов проверьте wikipedia link.

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

Семафоры, с другой стороны, являются более общим случаем (мьютексы на самом деле являются частным случаем семафора), у которых есть счетчик, каждый поток будет увеличиваться/уменьшаться в зависимости от активации/деактивации семафора. Когда семафор достигает 0, он блокирует себя и поток, вызвавший его. Для получения дополнительной информации о семафорах отметьте wikipedia page

Если вы хотите получить более конкретный совет, я предлагаю вам предоставить информацию об операционной системе, на которую вы нацеливаетесь, и/или API, который вы используете, поскольку все, что связано с потоками (мьютексы , семафоры и т. д.) специфичны для ОС

+0

Lefteris, благодарю вас за ответ. Я использую библиотеку Boost и пытаюсь создать кросс-платформенное приложение как для Windows, так и для Linux. Я довольно новичок в многопоточном программировании, и я очень смущен различными технологиями связи. Мьютексы и семафоры, как вы уже упоминали, я также слышал о синхронизации с использованием очередей сообщений. Просто интересно, существует ли какой-либо «стандартный» подход. Спасибо. – 2607

+0

Это то, чего я пытаюсь достичь. У меня есть вектор объектов M, и каждый объект имеет N переменных-членов. Есть потоки X, и каждый из них может обращаться к любым переменным-членам любого объекта внутри вектора. Я пытаюсь добиться этого, а также иметь минимальный критический раздел, т. Е. Блокировать как можно меньше каждый раз. Благодарю. – 2607

+0

Если вы хотите, чтобы доступ был эксклюзивным с muttualy, то только один поток может получить доступ к одной из N-членных переменных в то время, когда вам придется использовать N мьютексов. Я не знаком с библиотекой boost, но я считаю, что у нее есть функция mutex, верно? – Lefteris

1

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

Предотвращение условий гонки в потоках с использованием взаимного исключения. Если доступен только один объект или ресурс, используйте мьютекс, примером может служить ЖК-дисплей или один объект, в противном случае при многократном использовании семафора примером может служить четыре порта USB. Ресурсы - это данные и устройства. Данные представляют собой переменные, объекты, структуры данных и т. Д. Устройства представляют собой ЖК-дисплей, принтеры, USB-порты и т. Д.

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

Если у вас уже есть код или контрольные значения, используйте инструкцию printf вместо cout до и после объекта в каждом потоке. См. Причину printf вместо cout here.

Все операционные системы имеют межпроцессное взаимодействие, но API отличается. Linux использует POSTIX API, а Windows использует Win32 или Windows API, но используются одинаково.

Чтение Материал http://drdobbs.com/cpp/199200938?pgno=1

^-Summarized некоторые статьи в то, что было написано

0

Это может или не может. Параллельная модификация - UB для большинства стандартов потоковой передачи, поэтому они не дают никаких гарантий относительно того, что произойдет. Как правило, с простыми типами одна или другая запись будет «выигрывать». (Некоторые платформы гарантируют это для выровненных, простых типов.) С сложными типами вы можете разрывать и заканчивать «промежуточным» значением.

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

Добавление элемента в голову связанного списка, как правило, включает в себя что-то вроде:

object->next = head->next; 
head = object; 

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

1

Если вы работаете в Linux или OS X, вы можете использовать один из инструментов valgrind (hellgrind или drd), чтобы обнаруживать некоторые обращения к памяти потоками без соответствующих мьютексов.

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

0

Кажется, никто не ответил, как отлаживать многопоточный код в реальном времени, что является ДЕЙСТВИТЕЛЬНО трудным. Просто очень короткие задержки заставляют программу вести себя по-разному, и ошибка может произойти только в случае определенных условий гонки. Это можно исследовать только с чрезвычайно быстрой трассировкой, для которой Visual Studio слишком медленная. Хуже того, метод трассировки становится очень медленным, когда два потока называют его одновременно.

Очень легко написать свою собственную, не блокирующую (!) Трассировку в память. Просто напишите информацию в кольцевой буфер. Мой C++ не достаточно хорошо, но в C# код будет выглядеть примерно так:

const int maxMessages = 0x100; 
const int indexMask = maxMessages-1; 
string[] messages = new string[maxMessages]; 
int messagesIndex = -1; 

public void Trace(string message) { 
    int thisIndex = Interlocked.Increment(ref messagesIndex) & indexMask; 
    messages[thisIndex] = message; 
} 

Более подробное описание этого подхода, который также собирает нити и информацию о времени и выводит след красиво находится по адресу: CodeProject: Отладка многопоточного кода в реальном времени 1