以下代码旨在返回尚未使用的最小非负整数。它是从多个线程调用的。如果样式看起来有点奇怪,那是因为这个类只能存在于一个只有头的库中。
class Unique
{
public:
static unsigned int getIndex()
{
boost::unique_lock<boost::mutex> lock(get().mutex);
unsigned int index = 0;
while (index < get().valueInUse.size() && 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 &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。
有什么想法吗?这段代码是线程安全的,不是吗?
答案 0 :(得分:5)
get
函数当然不是线程安全的,除非您保证在创建任何线程之前调用它一次。而且,由于您使用get
调用来获取互斥锁以保护其余代码,因此您肯定会在那里得到一些意想不到的结果。
std::vector<bool>
明确专门用于每个bool使用一位,这样可以改变迭代结果(它使用我相信的代理对象)。您是否尝试过使用deque
代替vector
作为测试?