只要不使用其他.cpp文件,静态原子变量就可以跨线程工作.其他方面它会以某种方式阻止写访问吗

static atomic variable works across threads as long as no other .cpp files are utilized other wise it blocks write access somehow?

本文关键字:其他 方面它 线程 工作 写访问 方式阻 变量 cpp 文件 静态 就可以      更新时间:2024-09-29

我正在学习多线程,下面有一个简单的程序来显示一些进展。我不明白为什么函数在.h文件或main.cpp文件中定义的第一个代码工作得很好。但是,如果我把startLineThread的定义放在一个新的.cpp文件中,比如tools.cpp,那么第二个线程似乎永远不会有机会写入calcProgress变量,尽管它是静态的。控制台只循环使用零,还忽略设置为false的计算bool标志,我可以在调试一段时间后看到第二个循环中的循环完成并打印";完成";到控制台,但main中的while循环会忽略Tools::computing==false并保持循环。

------------------------- tools.h with definition within it ----------------------------
#pragma once
#include <atomic>
#include <iostream>
#include "tools.h"
#include <thread>
#include <chrono>
namespace Tools
{
static std::atomic<float> clacProgress;
static volatile bool cFinished;
static volatile bool calculating;
void startLineThread()
{
std::cout << " second thread active " << std::endl;
float dataPoints = 1000;
float dt = 0.5;
for (float t = 0.0f; t < dataPoints; t++)
{
// bs code for making this thread slightly slower maybe
float no = 87 + 45;
int slow = 45 * 56 * 23;
std::this_thread::sleep_for(std::chrono::microseconds(8));
Tools::clacProgress = t;
}
//Tools::cFinished = true;
Tools::calculating = false;
std::cout << "done" << std::endl;
}

}
// this way works fine calcProgress is incremented and printed with updated value
// and the while loop in main exits when calculating becomes false;
-------------------------------main.cpp ----------------------------------------
#include <vector>
#include <string>
#include <stdio.h>
#include <math.h>
#include <chrono>
#include <sstream>
#include <thread>
#include "tools.h"
#include <atomic>

int main()
{
std::cout << " main thread active " << std::endl;
// initilize all statics before any other threads are active
//Tools::clacProgress = 0; 
Tools::calculating = true;
Tools::cFinished = false;
std::thread testCalc(Tools::startLineThread);
while ( Tools::calculating)
{
std::cout << Tools::clacProgress << std::endl;
std::this_thread::sleep_for(std::chrono::microseconds(200));
}
std::cin.get();

}
------------------------------------------------------------------------------

现在,如果我把startLineThread的定义放在tools.cpp文件中,它会破坏一切。

---------------------------- tools.h startLineThread declared but not defined -------
#pragma once
#include <atomic>
namespace Tools
{
static std::atomic<float> clacProgress;
static volatile bool cFinished;
static volatile bool calculating;
void startLineThread();

}
----------------------------- tools.cpp ------------
#include <iostream>
#include "tools.h"
#include <thread>
#include <chrono>
void Tools::startLineThread()
{
std::cout << " second thread active " << std::endl;
float dataPoints = 1000;
float dt = 0.5;
for (float t = 0.0f; t < dataPoints; t++)
{
// bs code for making this thread slightly slower maybe
float no = 87 + 45;
int slow = 45 * 56 * 23;
std::this_thread::sleep_for(std::chrono::microseconds(8));
Tools::clacProgress = t;
}
//Tools::cFinished = true;
Tools::calculating = false;
std::cout << "done" << std::endl;
}
/* this way calcProgress is never incremented in the main thread and prints zero's despite the second thread kicking off and looping and I see " done " printed which indicates it did loop and the while loop in main never exits despite calculating becoming false */
-------------------------------main.cpp ----------------------------------------
#include <vector>
#include <string>
#include <stdio.h>
#include <math.h>
#include <chrono>
#include <sstream>
#include <thread>
#include "tools.h"
#include <atomic>

int main()
{
std::cout << " main thread active " << std::endl;
// initilize all statics before any other threads are active
//Tools::clacProgress = 0; 
Tools::calculating = true;
Tools::cFinished = false;
std::thread testCalc(Tools::startLineThread);
while ( Tools::calculating)
{
std::cout << Tools::clacProgress << std::endl;
std::this_thread::sleep_for(std::chrono::microseconds(200));
}
std::cin.get();

}
------------------------------------------------------------------------------

如果这是一种比赛条件,我不明白为什么我在一种情况下会有这种情况,而不是另一种情况?但我认为静态原子会阻止线程更新/报告进度值的竞争条件

这些变量不应该在头文件中定义:

static std::atomic<float> clacProgress;
static volatile bool cFinished;
static volatile bool calculating;

通过在头中定义它们,您可以为每个.cpp文件中的每个变量制作一个单独的副本。假设您使用的是C++17或更新版本,请将static更改为inline。如果您使用的是C++14或更低版本,请将static更改为extern,然后在.cpp文件中定义变量(因此每个变量都有一个副本,请参阅头文件C++中的声明变量(。

相关文章: