我需要一个线程安全计数器来记录当前类型为 Apple
的对象数。 我试图用 OpenMP 制作一个简单的,但我不明白为什么计数不正确。 以下是该类的简化,包含实际测试代码和实际输出:
类
class Apple {
public:
Apple();
~Apple();
static int getThreadCount();
private:
static int threadCount;
void threadCountIncrease();
void threadCountDecrease();
};
Apple::Apple() {
threadCountIncrease();
}
Apple::~Apple() {
threadCountDecrease();
}
void Apple::threadCountIncrease() {
#pragma omp critical(AppleThreadCount)
{
std::cout << "## COUNT ++" << "n";
++threadCount;
}
}
void Apple::threadCountDecrease() {
#pragma omp critical(AppleThreadCount)
{
std::cout << "## COUNT --" << "n";
--threadCount;
}
}
测试代码
std::vector<Apple> apples;
cout << Apple::getThreadCount() << "n";
for(int i=0; i<3; ++i) {
apples.push_back(Apple());
cout << Apple::getThreadCount() << "n";
}
我不明白的输出
## COUNT ++
## COUNT --
0
## COUNT ++
## COUNT --
## COUNT --
-1
## COUNT ++
## COUNT --
## COUNT --
## COUNT --
-3
## COUNT --
## COUNT --
## COUNT --
为什么"COUNT --"出现次数多于"COUNT ++"次数? 为什么最后显示的计数是 -3 而不是 3?
多亏了公认的答案,我最终放弃了我正在做的事情,转而支持这个解决方案。
我首先要指出的是,我的解释可能并不完全技术正确。
发生的一件事是,当您执行apples.push_back(Apple());
时,将创建元素的副本。由于尚未定义复制构造函数,因此不会为此副本调用threadCountIncrease
。
因此,您最终将获得至少两倍于++
--
.
除此之外,当std::vector
大小增加时,还需要分配更多内存。根据实现的不同,这将导致重新分配或数据副本。在您的情况下,确实会出现额外的副本。
当您在循环之前添加apples.reserve(10);
时,您将看到--
计数会减少,因为std::vector
已经为至少 10
个元素保留了空间。