[使用 Visual Studio Professional 2012 的 C++]
大家好,我在使用 std::mutex 来阻止 main() 更改第二个线程正在访问的变量时遇到问题。在下面的示例中(这是我的实际程序的大规模简化表示),函数 update() 从 main() 中的 std::thread t2 运行。 update() 检查 vector world.m_grid[i][j].vec 是否为空,如果不是,则修改包含的值。 main() 也会访问并偶尔清除该 vector ,因此,如果 main() 在 update() 中的空检查之后但在修改 world.m_grid[i][j].vec[0] 之前清除该 vector ,您会得到 vector 下标超出范围错误。我试图使用 std::mutex 来防止这种情况发生,方法是在 update() 空检查之前锁定屏障,并在 world.m_grid[i][j].vec[0] 被 update() 修改后释放它,在广泛浏览互斥体教程和示例后,我无法理解为什么以下内容没有达到预期的效果:
#include <cstdlib>
#include <thread>
#include <mutex>
#include <vector>
using namespace std;
mutex barrier;
class World
{
public:
int m_rows;
int m_columns;
class Tile
{
public:
vector<int> vec;
int someVar;
};
vector<vector<Tile> > m_grid;
World (int rows = 100, int columns = 200): m_rows(rows), m_columns(columns), m_grid(rows, vector<Tile>(columns)) {}
};
void update(World& world)
{
while (true)
{
for (int i = 0; i < world.m_rows; ++i)
{
for (int j = 0; j < world.m_columns; ++j)
{
if (!world.m_grid[i][j].vec.empty())
{
lock_guard<mutex> guard(barrier);
world.m_grid[i][j].vec[0] += 5;
}
}
}
}
}
int main()
{
World world;
thread t2(update, ref(world));
while (true)
{
for (int i = 0; i < world.m_rows; ++i)
{
for (int j = 0; j < world.m_columns; ++j)
{
int random = rand() % 10;
if (world.m_grid[i][j].vec.empty() && random < 3) world.m_grid[i][j].vec.push_back(1);
else if (!world.m_grid[i][i].vec.empty() && random < 3) world.m_grid[i][j].vec.clear();
}
}
}
t2.join();
return 0;
}
我一定错过了一些基本的东西。理想情况下,解决方案只是锁定 world.m_grid[i][j] (让 main() 可以访问 world.m_grid 的其余部分),我认为这将涉及在“Tile”类中包含互斥锁,但我遇到了与此处描述的问题相同:Why does std::mutex create a C2248 when used in a struct with WIndows SOCKET?并且无法将所描述的解决方案适应我的项目,因此如果有人也能够帮助我,那将会非常有帮助。
-感谢您的宝贵时间。
[编辑]拼写
最佳答案
当您访问数组时,您还需要在主函数中锁定互斥锁:
...
for (int j = 0; j < world.m_columns; ++j) {
lock_guard<mutex> guard(barrier);
int random = rand() % 10;
if (world.m_grid[i][j].vec.empty() && random < 3) world.m_grid[i][j].vec.push_back(1);
else if (!world.m_grid[i][i].vec.empty() && random < 3) world.m_grid[i][j].vec.clear();
}
...
使用互斥体,您需要保护对数据的所有访问。到目前为止,在您的代码中,线程 2 在访问数据时会生成一个互斥体。然而,主线程可以更改代码,因为它不知道有关互斥体的任何信息。所以主线程可以简单地改变数据。
关于c++ - 无法获取 std::mutex 来正确保护线程访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14597092/