#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 .