【发布时间】:2020-11-09 18:46:46
【问题描述】:
如果这已发布在其他任何地方,我非常抱歉,但我找不到任何匹配的内容。
在一个类中,我们发现了一个预先设计的槽分配器,它存储了线程可以获取的指定数量的槽。如果需要一个槽,则该槽应该工作,否则它会被阻塞,直到另一个线程释放。代码如下所示:
struct slot_allocator_mutexes
{
private:
int num_slots = 8;
vector<bool> slots;
vector<mutex> mutexes;
public:
slot_allocator_mutexes() : slots(num_slots, false), mutexes(num_slots) {}
int acquire_slot()
{
while(true)
{
for (int i = 0; i < num_slots; ++i)
{
mutexes[i].lock();
vector<bool>::reference slot_ref = slots[i];
if (slot_ref == false)
{
slot_ref = true;
mutexes[i].unlock();
return i;
}
mutexes[i].unlock();
}
}
}
void release_slot(int slot)
{
mutexes[slot].lock();
assert(slots[slot] == true);
slots[slot] = false;
mutexes[slot].unlock();
}
};
将通过
调用 for (int t = 0; t < thread_numbers; ++t)
{
threads.push_back(thread([&]() {
for (int r = 0; r < repeats; ++r)
{
int slot = alloc.acquire_slot();
cout_lock.lock();
cout << "iteration num: " << r << endl;
cout << "Current slot: " << slot << " in thread number " << pthread_self() << endl;
cout_lock.unlock();
alloc.release_slot(slot);
}
}));
}
澄清一下:我知道可能会有更简洁的实现 - 不过这不是我的问题。
我的任务是确定这是否是分配器的正确线程安全实现。使用断言assert(slots[slot] == true); 我很快就发现,有些东西不起作用。在进行了研究和多种测试方法之后,我必须承认我没有想法......
我不明白为什么这不起作用。我最初的想法是mutexes[i].lock(); 可能是问题所在,但由于这只是一个读取操作,所以这并不是真正的答案。
谢谢。
【问题讨论】:
-
您似乎没有向我们提供所有代码。
m是什么?我看到m.unlock()。此外,您似乎在构造函数中命名为mutexeslocks。请确保您的最小可重现示例没有这些差异,否则它实际上只是一个猜谜游戏 -
@Human-Compiler 对这些错误非常抱歉,我更改了一些代码并且从那时起没有编译。现在应该可以工作了
-
您还没有发布minimal reproducible example。无论如何,答案实际上是一个非常奇怪的 c++ 怪癖,我相信一些 c++ 标准的作者现在非常后悔。如果您尝试用
auto替换难看的显式类型名称并想知道为什么编译器拒绝该代码,您会发现问题。 -
@EOF 我想你说的是
vector<bool>::reference slot_ref = slots[i];?如果我将其更改为自动它仍然为我编译...? -
但是如果你把它改成
auto slot_ref = slots[i];,你就改变了意思,因为slot_ref不是一个引用而是一个副本。
标签: c++ multithreading mutex