std::deque<T> dq;
Thread_function(pointer to queue as argument) // created 8 threads
{
vertext_found = true;
**v is initialized to NULL
while ( i < dq->size())
{
EnterCriticalSection(&h);
if( i < dq.size() ) {
v = dq.at(i); // accessing element of queue without popping
i++;
vertext_found = true;
}
LeaveCriticalSection(&h);
if (vertext_found && (i < dq.size()) && v != NULL)
{
**operation on 'v'
vertext_found = false;
}
}
}
Будет ли это условие гонки данных, особенно при обработке?в то время как я < dq-> размер ())«за пределами критического раздела? Мой подход правильный? В противном случае, пожалуйста, предложите мне.
Будет ли это невмешательство в многопоточную среду?
В тексте вашего вопроса, dq
(как и все другие переменные в вашей функции) является местный объект:
std::deque<T> dq;
Если это действительно так, то на вопрос есть простой ответ: «Да». Это потокобезопасно, потому что нет конфликта: каждый поток работает на локальном объекте, и поскольку нет общего доступа, не может быть никакой гонки данных.
Теперь предположим, что ваш код предназначен для демонстрации использования общий структура данных, и это dq
на самом деле глобальный объект или что-то как-то доступно одновременно нескольким потокам (это то, что dq->size()
вызов функции, кажется, предлагает), тогда ответ «Это зависит».
Если все ваши потоки одновременно выполняют только ту функцию, которую вы показываете, и dq
ссылка или указатель на const
, так что ваша функция не содержит никакого вызоваconst
функции-члены, то ответ «Да, но тебе не нужно любой критическая секция вообще в этом случае «. Пункт 17. 6.5.9 / 3 Стандарта C ++ 11 определяет:
Стандартная библиотечная функция C ++ не должна прямо или косвенно изменять объекты (1.10), доступные для потоков
кроме текущего потока, если к объектам не обращаются напрямую или косвенно через функциюconst
аргументы, в том числеthis
,
Ссылка на пункт 1.10 (и, в частности, на 1.10 / 21), который определяет, что такое гонки данных, проясняет значение вышеприведенного абзаца:
Выполнение программы содержит гонку данных, если она содержит два конфликтующие действия в разных темах,
по крайней мере, один из которых не является атомарным, и ни один не происходит раньше другого. Любая такая гонка данных приводит к
неопределенное поведение. […]
Наконец, пункт 1.10 / 4 определяет, когда два действия конфликтуют:
Две оценки выражений конфликтуют, если одна из них изменяет ячейку памяти (1.7), а другая —
осуществляет доступ или изменяет одну и ту же ячейку памяти.
Из всего этого следует, что const
функции-члены обязательно потокобезопасны. Вы можете быть заинтересованы в просмотре эта презентация Херб Саттер об этом.
поскольку deque<T>::size()
это const
функция-член и at()
это const
функция-член (потому что вы вызываете ее из ссылки или указателя на const
) который возвращает ссылку на const
, нет необходимости синхронизировать доступ из нескольких потоков.
Если твой dq
является не ссылка или указатель на const
, тогда ответ «нет«, так как at()
это неconst
функция-член. Более того, так как v
неконстантная ссылка на элемент, ваша «операция над v
«может быть неconst
поэтому вводя гонку данных на элементы из dq
а не на dq
сам.
Так же, если ваши потоки одновременно обращаются и изменяют dq
через другие функции, тогда ответ снова «Нет», потому что вы не защищаете все доступы к общему объекту. Операции чтения конфликтуют с операциями записи (см. Выше), и вы защищаете только немного из них. В этом случае ваш критический раздел должен охватывать весь while
цикл.
Других решений пока нет …