gpt4 book ai didi

c++ - 使用一个对象线程中的 const 方法是否安全?

转载 作者:行者123 更新时间:2023-11-28 00:07:21 29 4
gpt4 key购买 nike

我不确定这是否重复,我浏览了很多帖子,但它们似乎与我的问题不够接近。

我想使用一个对象的 const 方法来同时更改其他对象。该程序基本上需要我在重力的影响下移动一个粒子,我想对所有粒子并行运行。我开设了一门物理课,在该课中我有一个 const 方法来移动粒子对象。

这里有一些示例类可以更好地理解我。

/**
* Particle.h
*/
#ifndef __Particle__sim__
#define __Particle__sim__

class Particle {
private:
double height;
double velocity;
public:
const double getHeight() const;
const double getVelocity() const;
void setHeight(const double&);
void setVelocity(const double&);
};

#endif

/**
* Physics.h
*/
#ifndef __physics__sim__
#define __physics__sim__

#include <thread>
#include <vector>

#include "Particle.h"

class Physics {
private:
double gravity;
double timeStep;
void moveParticle(Particle&, const double) const;

public:
Physics(const double g, const double t);
void moveParticles(std::vector<Particle>&, const double) const;
};

#endif

/**
* Physics.cpp
*/
#include "Physics.h"

using namespace std;

Physics::Physics(const double g, const double t) : gravity(g), timeStep(t) {}

void Physics::moveParticle(Particle& particle, const double time) const {
// move particle under gravity
}

void Physics::moveParticles(vector<Particles>& particles, const double time) const {
vector<thread> threads;
threads.reserve(particles.size());

for (auto& p : particles) {
threads.push_back(thread(Physics::moveParticle&, this, std::ref(p), time));
}
for (auto& t : threads) {
t.join();
}
}

这基本上是我的主要内容

/**
* main.cpp
*/

#include <vector>

#include "Physics.h"
#include "Particle.h"

using namespace std;

int main() {
vector<Particle> particles;
// insert 100,000 particles

Physics physics = Physics(-9.81, 0.01);

physics.moveParticles(particles, 5.0);

return 0;
}

physics.moveParticle(Particle&, const double) 线程在这里安全吗?

简短而甜美:我想使用一个 Physics 对象的方法来创建多个线程来移动程序中的所有粒子,但我不确定我编写的 const 方法是否是线程安全的。我不明白为什么不这样做,但我无法证明这一点。

最佳答案

乍一看,这应该是线程安全的。

我们需要查看 Particle::setHeight 的实现才能绝对确定。如果它执行类似写入全局数组的操作怎么办?这会很愚蠢,但我们不能确定。

但是,您的 Particle 看起来非常简单。更线程安全的是根本不改变它。使它们不可变,并在每次计算时创建一个新的。

您仍然可以通过将新粒子分配回旧粒子来更改它们。

但是,如果你真的想进入线程,这里的一个很棒的技术是拥有两个世界状态:previous 和 next。这些与每个更新步骤交换。每个更新步骤都从上一个读取并写入下一个。这可以让其他线程(如图形显示)读取以前的内容,而无需不断锁定诸如粒子之类的小东西。

有了这个,一个不可变的粒子根本不会减慢任何东西。事实上,编译器会将 nextParticles[i] = updateParticle(prevParticles[i]) 的机器代码重写为直接赋值给它在内存中的最终位置。那是 RVO 或 NRVO。

关于c++ - 使用一个对象线程中的 const 方法是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34778523/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com