C++:在多线程处理时访问类数据成员的混淆
C++: confusion about accessing class data members while multithreading
我有以下最小工作示例,其中我在向量chains
中创建了多个markov_chain
对象,在向量workers
中创建了相等数量的thread
对象,每个对象在相应的markov_chain
对象上执行markov_chain
类成员函数sample
。此函数获取某个整数(以下示例中为99(,并将其分配给markov_chain
对象的acceptance
公共数据成员。然后,我为矢量中的每个对象打印acceptance
的值。
#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
class markov_chain
{
public:
unsigned int length{0}, acceptance{0};
markov_chain(unsigned int l) {length=l;}
~markov_chain() {}
void sample(int acc);
};
void markov_chain::sample(int acc)
{
acceptance = acc;
std::cout << length << ' ' << acceptance << std::endl;
}
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains;
std::vector<std::thread> workers;
for (int i = 0; i <= number_of_threads; i++) {
chains.push_back(markov_chain(number_of_samples));
workers.push_back(std::thread(&markov_chain::sample, chains[i], 99));
}
std::for_each(workers.begin(), workers.end(), [](std::thread &t)
{
t.join();
});
for (int i = 0; i <= number_of_threads; i++) {
std::cout << chains[i].length << ' ' << chains[i].acceptance << std::endl;
}
return 0;
}
执行后,程序输出
1000 99
1000 99
1000 99
1000 99
1000 0
1000 0
1000 0
1000 0
因此,程序未能更改向量chains
中对象的acceptance
的值。我不知道为什么会发生这种事;当我在不创建线程的情况下使用函数CCD_ 13时。
您的代码有两个问题:
-
在创建每个
std::thread
时,您将传递每个对象的副本作为sample()
的this
参数。 -
按照您的方式将多个对象推入
chains
向量可能会导致向量重新分配其内部数组,从而使您已经传递给现有线程的任何对象指针无效,因为这些原始对象在重新分配后就不见了。
在创建任何线程之前,您需要完全初始化chains
向量。您需要将指向每个对象的指针传递给每个线程。
您可以提前reserve()
阵列,以避免在推入时重新分配,例如:
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains;
std::vector<std::thread> workers;
chains.reserve(number_of_threads);
for (int i = 0; i < number_of_threads; ++i) {
chains.push_back(markov_chain(number_of_samples));
workers.push_back(std::thread(&markov_chain::sample, &chains[i], 99));
}
for(auto &t : workers) {
t.join();
}
for (auto &c : chains) {
std::cout << c.length << ' ' << c.acceptance << std::endl;
}
return 0;
}
演示
然而,由于所有对象都是用相同的起始值初始化的,因此一种更简单的方法是完全去掉chains.push_back()
,转而使用chains.resize()
,例如:
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains;
std::vector<std::thread> workers;
chains.resize(number_of_threads, markov_chain(number_of_samples));
for (int i = 0; i < number_of_threads; ++i) {
workers.push_back(std::thread(&markov_chain::sample, &chains[i], 99));
}
for(auto &t : workers) {
t.join();
}
for (auto &c : chains) {
std::cout << c.length << ' ' << c.acceptance << std::endl;
}
return 0;
}
演示
或者,甚至使用vector
构造函数本身:
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains(number_of_threads, markov_chain(number_of_samples));
std::vector<std::thread> workers;
for (int i = 0; i < number_of_threads; ++i) {
workers.push_back(std::thread(&markov_chain::sample, &chains[i], 99));
}
for(auto &t : workers) {
t.join();
}
for (auto &c : chains) {
std::cout << c.length << ' ' << c.acceptance << std::endl;
}
return 0;
}
演示
相关文章:
- 用于访问容器<T>数据成员的正确 API
- 使用指针访问数组中的对象数据成员
- 友元函数无法访问私有数据成员 (c++)
- 在类 A 中创建类型为 B 类的向量 - 访问数据 [C++] [成员在两个类中都是私有的]
- 访问数据成员(本身是对象)的数据成员,就好像它们是类成员一样
- 使公共数据成员在C++中无法访问
- 有没有办法在C++中循环访问对象的不同数据成员
- 为什么类成员数据必须是静态的才能被模板化类的模板化结构成员访问
- 如何在C++中使用类对象访问指针数据成员
- 通过指针算法访问结构数据成员
- 是否可以访问类数据成员并在析构函数中对它们执行操作?
- 如何在 c++ 中访问类的私有数据成员
- 现代C++编译器是否优化了对类中同一数据成员的重复访问?
- 无法访问派生类函数内的基类的受保护数据成员
- 从私有结构数据成员访问类公共成员函数C++
- 有关C++/组件数据布局、数据成员访问、方法的一般问题
- C++ 共享库不允许静态数据成员访问
- 私人数据成员访问
- OpenCV Mat数据成员访问
- 数据成员访问歧义和菱形继承