我正在尝试使用一个线程来阻止竞争条件,我将一些变量传递给std :: ref,但不太确定如何操作。
我基本上得到了:
#include <thread>
#include <mutex>
#include <vector>
std::mutex mtx;
float getXData();
float getYData();
void plot(std::vector<float> x, std::vector<float> y);
void calculateMeasurements(bool& currentlyRunning, std::vector<float>& xMeasurements,
std::vector<float>& yMeasurements){
while (true){
xMeasurements.push_back(getXData());
yMeasurements.push_back(getYData());
...
if (someCondition){
currentlyRunning=false;
xMeasurements.clear();xMeasurements.push_back(0);
yMeasurements.clear();yMeasurements.push_back(0);
currentlyRunning=true;
}
}
}
int main(){
std::vector<float> xMeasurements;
std::vector<float> yMeasurements;
xMeasurements.push_back(0);
yMeasurements.push_back(0);
bool currentlyRunning{true};
auto thread = std::thread(calculateMeasurements, std::ref(currentlyRunning),
std::ref(xMeasurements), std::ref(yMeasurements));
while (true){
...
mtx.lock();
if(currentlyRunning==true && xMeasurements.size()==yMeasurements.size()){
plot(xMeasurements,yMeasurements);
}
}
mtx.unlock();
}
基本上发生的事情是,后台有一个线程将元素推回到xMeasurements和yMeasurements,偶尔也会将xMeasurements和yMeasurements重置为0的一个元素。 功能图要求xMeasurements和Ymeasurements具有相同的大小。
我认为std :: mutex :: lock使得std :: mutex :: lock和std :: mutex :: unlock之间的所有变量只能由调用std :: mutex :: lock的线程编辑,直到它解锁,所以在这里它应该防止其他线程改变currentRunning,xMeasurements&amp; yMeasurements。然而,它偶尔会在线上失败(xMeasurements,yMeasurements);因为xMeasurements.size()!= yMeasurements.size()(所以情节试图在xMeasurements.push_back(getXData());和yMeasurements.push_back(getYData());之间读取它,如果我对mutex如何正确工作不应该发生,因为它检查它们在锁内的大小相同)或者它失败,因为xMeasurements或yMeasurements都是空的(如果我正确的互操作如何工作不应该发生因为它检查currentRunning == true在锁定中,当currentRunning == false时它们只能为空。
如何正确阻止另一个线程更改通过引用传递的变量?
由于
答案 0 :(得分:1)
std :: mutex :: lock 不保护它与std :: mutex :: unlock之间的变量。可以将其视为保护代码段。每次访问和编辑由线程修改的全局数据结构时,都需要锁定和解锁。在线程方法中编辑xMeasurements和yMeasurements时,请确保锁定。当我使用线程编程时,我通常喜欢为每个全局结构引入一个可能导致竞争条件的互斥锁,但是你可以在这里使用一个。
#include <thread>
#include <mutex>
#include <vector>
std::mutex mtx;
float getXData();
float getYData();
void plot(std::vector<float> x, std::vector<float> y);
void calculateMeasurements(bool& currentlyRunning, std::vector<float>& xMeasurements,
std::vector<float>& yMeasurements){
while (true){
std::lock_guard<std::mutex> lg(mtx);
xMeasurements.push_back(getXData());
yMeasurements.push_back(getYData());
...
if (someCondition){
currentlyRunning=false;
xMeasurements.clear();xMeasurements.push_back(0);
yMeasurements.clear();yMeasurements.push_back(0);
currentlyRunning=true;
}
}
}
int main(){
std::vector<float> xMeasurements;
std::vector<float> yMeasurements;
xMeasurements.push_back(0);
yMeasurements.push_back(0);
bool currentlyRunning{true};
auto thread = std::thread(calculateMeasurements, std::ref(currentlyRunning),
std::ref(xMeasurements), std::ref(yMeasurements));
while (true){
...
std::lock_guard<std::mutex> lg(mtx);
if(currentlyRunning==true && xMeasurements.size()==yMeasurements.size()){
plot(xMeasurements,yMeasurements);
}
}
}