C ++ STL карта / вектор векторов и безопасность потоков - PullRequest
3 голосов
/ 18 января 2011

Мне было интересно, будет ли следующий код считаться поточно-ориентированным. Я думаю, что это должно быть, но я не слишком знаком с тем, что происходит под капотом.

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

void Foo::func( vector<int> v)

В Foo у меня также есть личный член,

vector< vector<int> > vecOfVec;

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

void Foo::func( vector<int> v)
{
    int size = v.size();
    int index = vecOfVec.size();

    vecOfVec.push_back(v);

    if (size < 1000)
    {
        boost::thread t( boost::bind( &Foo::PushBackZeros, this, vecOfVec, index) );
    }
}

Foo::PushBackZeros будет, как следует из названия, просто заполнить вектор в 'vecOfVec [index]' нулями, пока его размер не увеличится до 1000;

Теперь я не вижу каких-либо одновременных операций чтения или записи ни для одного из элементов vecOfVec. Очевидно, что есть вероятность одновременных операций над всем объектом, но никогда не будет одновременностей с конкретным элементом vecOfVec.

Может ли кто-нибудь объяснить, будет ли вышеизложенное считаться поточно-ориентированным? Будет ли такая же степень и для карт STL? Если нет, пожалуйста, объясните. Ура!

Ответы [ 3 ]

8 голосов
/ 18 января 2011

Я думаю, что это не потокобезопасно. Что происходит, если один поток помещает новый элемент в вектор, что приводит к необходимости увеличения области внутренней памяти вектора? Выталкивающий поток может обменять память на больший буфер, что может привести к тому, что потоки, читающие параллельно с этой операцией, внезапно прочитают из недействительной (устаревшей) памяти. Или потоки, которые видят случайные значения в определенных слотах, просто потому, что они одновременно читают код, который копирует содержимое вектора из старой ячейки памяти в новую.

0 голосов
/ 18 января 2011

vecOfVec передается по значению, потому что boost :: bind требует, чтобы вы поместили boost :: ref вокруг ссылочного параметра.

Скорее всего, потокобезопасен, но не делает то, что вы думаете.

Я не уверен, зачем вам нужно передавать этот параметр, так как он уже в "this".

Чтобы ответить на оригинальный вопрос, хотя для того, что вы хотите сделать:

  • Если можно изменить размер vecOfVecs, то любой из его членов может быть признан недействительным, поэтому он не будет поточно-ориентированным.
  • Вставка элементов в один из внутренних векторов не приведет к аннулированию других векторов-членов, поэтому у вас могут быть разные потоки, заполняющие разные элементы вектора одновременно, если они все уже есть.
  • Если вы заранее «резервируете», то можете добавить в свой вектор больше участников, пока эта емкость не будет достигнута, и это не сделает недействительными существующие элементы.
0 голосов
/ 18 января 2011

Если ваша Foo::PushBackZeros имеет такую ​​же подпись, как и Foo::func( vector<int> v), то она будет поточно-ориентированной, поскольку вы передаете копию массива этой функции.Таким образом, одновременного доступа не будет.

...