使用std :: ref和Thread

时间:2017-06-23 18:55:36

标签: c++ multithreading c++11

我正在尝试使用一个线程来阻止竞争条件,我将一些变量传递给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时它们只能为空。

如何正确阻止另一个线程更改通过引用传递的变量?

由于

1 个答案:

答案 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);
         }
    }
}