Являются ли функции, вызываемые параллельным неупорядоченным поиском по карте, потокобезопасными?

Предположим, у меня есть следующий код:

#include<concurrent_unordered_map.h>

struct firstStruct {
<irrelevant code>
}
struct secondStruct {
    void func(){ 
       <CRITICAL CODE>
    }
}

Предположим, у меня есть это:

concurrent_unordered_map<firstStruct,secondStruct> cmap = ...

и давайте предположим, что cmap был заполнен, и что firstStruct f и secondStruct s представляют собой пару (key,value)(f,s), которая существует в cmap.

Если бы я использовал следующий фрагмент кода

cmap[f].func();

Будет ли выполнение <CRITICAL CODE> в func() из secondStruct s поточно-ориентированным?

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

cmap[f].func();

а также

SecondStruct s2 = ... ;
cmap[f] = s2;

Если пара (key,value)(f,s) была изменена на (f,s2) одним потоком, что произойдет, если другой поток выполнит <CRITICAL CODE>?

2
0
46
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Из предложение для concurrent_unordered_map

For serialized execution, the operations behave the same as their current STL counterparts. The only change is allowance for concurrency. Executing any of the following operations concurrently on a concurrent unordered container does not introduce a data race:

get_allocator
empty, size, max_size
begin, end, cbegin, cend
insert
find, count, equal_range, operator[], at
load_factor
max_load_factor() 
operator==, operator!= 

assuming that the requisite operations on the key type (and mapped_type if applicable) are concurrency safe.

emphasis mine

Итак, operartor[] является потокобезопасным, но операция, которую вы выполняете с его возвращаемым значением, также должна быть потокобезопасной, чтобы гарантировать отсутствие гонки за данными. Это означает, что <CRITICAL CODE> в func() сам должен быть потокобезопасным. Если это не так, то что-то вроде

cmap[f].func();
SecondStruct s2 = ... ;
cmap[f] = s2;

Также не будет потокобезопасным, поскольку функция все еще будет работать, пока вы назначаете новый объект ключу.

Большое спасибо! Это развеяло некоторые сомнения, которые у меня были в нескольких местах моего кода. Чтобы обойти это, я подумал о том, чтобы изменить cmap следующим образом: concurrent_unordered_map<firstStruct,std::shared_ptr<secondS‌​truct>> cmap = ... с вызовом func следующим образом: std::shared_ptr<secondStruct> temp_ptr = cmap[f]; temp_ptr->func(); будет ли это потокобезопасным? вообще есть ли лучший способ сделать это, сохранив безопасность потоков, а также обеспечив быстрое выполнение? Здесь я должен указать, что скорость имеет большое значение в моем коде.

glopquestions 13.09.2018 18:21

@glopquestions Это будет потокобезопасным, если никто не сделает что-то вроде *cmap[f] = s2; (назначить указанному объекту вместо назначения нового указателя). Если они назначат новый указатель, все будет в порядке, но если они изменят базовый объект на вас, вы окажетесь в той же лодке.

NathanOliver 13.09.2018 18:24

Я думал, что назначение с использованием cmap[f] = std::make_shared<secondStruct>(s2); является ли это потокобезопасным? (Чтобы уточнить, сопоставление f с тем же общим указателем, но изменение того, на что указывает общий указатель (что-то другое, что я хочу), опасно), но (отображение f на новый общий указатель и наличие этого нового общего указателя указать на все, что я хочу, безопасно?)

glopquestions 13.09.2018 18:37

@glopquestions Да, это было бы потокобезопасным. cmap[f] будет переназначен на std::make_shared<secondStruct>(s2), но поскольку temp_ptr существует, объект, для которого вы вызываете функцию, все еще будет жив.

NathanOliver 13.09.2018 18:40

@glopquestions Безопасность потоков - свойство относительное. Вопрос о том, является ли отдельная операция поточно-ориентированной, является ошибкой категории. Имеет смысл спросить, являются ли две или более операций относительно потокобезопасными. Вы даже можете спросить, являются ли два вызова одной и той же операции потокобезопасными друг для друга. В этих комментариях есть операции, которые являются потокобезопасными с кодом в этих комментариях; есть другие операции, которые не являются потокобезопасными с кодом в этих комментариях. Если вы спросите, как вы это делаете, другой стороне придется читать ваши мысли, и если они ошибаются, они дадут неправильный ответ, и вы будете в блаженном неведении.

Yakk - Adam Nevraumont 13.09.2018 19:00

Другие вопросы по теме