Многопоточный код: векторные итераторы несовместимы

#c #visual-studio #multithreading

#c #visual-studio #многопоточность

Вопрос:

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

 class Unique
{
public:
    static unsigned int getIndex()
    {
        boost::unique_lock<boost::mutex> lock(get().mutex);
        unsigned int index = 0;
        while (index < get().valueInUse.size() amp;amp; get().valueInUse[index])
            index  ;
        if (index == get().valueInUse.size()) get().valueInUse.push_back(true);
        get().valueInUse[index] = true;
        return index;
    }
    static void releaseIndex(unsigned int index)
    {
        boost::unique_lock<boost::mutex> lock(get().mutex);
        get().valueInUse[index] = false;
    }
private:
    static Unique amp;get()
    {
        static Unique s;
        return s;
    }
    boost::mutex mutex;
    std::vector<bool> valueInUse;
};
  

С этим кодом иногда возникает проблема во время отладки:

 vector<bool> iterators incompatible
  

Трассировка стека показывает, что проблема, возникающая при push_back() index , равна нулю. Реализация STL, похоже, думает, что она вставляет в end() другой экземпляр vector<bool> . Использование Visual Studio 2010 Express.

Есть идеи? Этот код потокобезопасен, не так ли?

Комментарии:

1. Вместо vector<bool> вы можете использовать std::bitset ( cplusplus.com/reference/stl/bitset ).

2. @yasouser однако вам нужно знать размер bitset во время компиляции.

3. Также смотрите раздел под названием «Векторная специализация: vector<bool>» по этой ссылке: cplusplus.com/reference/stl/vector . В нем конкретно говорится о ссылках на элементы в vector<bool .

Ответ №1:

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

std::vector<bool> явно специализирован на использовании одного бита на bool, чтобы изменять результаты итерации (я полагаю, что он использует прокси-объект). Вы пробовали использовать deque вместо vector просто в качестве теста?

Комментарии:

1. Также рассмотрите boost . dynamic_bitset .