std::线程通信问题

std::thread communication issue

本文关键字:问题 通信 线程 std      更新时间:2023-10-16

我正在构建一个多线程应用程序,但遇到了一个问题。在应用程序中,我使用一个变量在线程之间进行通信,但它不起作用。因此,当您键入exit时,应用程序不会停止执行。

代码:

//Program that controls an cadrocopter with the use of a
//Raspberry Pi, MPU 6050, an ultrasonic sensor, an HMC5883L and Arduino Leonardo
//to compile use "g++ ./quad.cpp -o ./quad -std=c++0x -pthread"
//
//Copyright Jan Hendrik Farr
#include <iostream>             //used to input data
#include <string>               //used to procces the userdata
#include <stdlib.h>             //used to convert strings into floats
#include "./serial/serial.h"    //used to communicate with the Arduino
#include <thread>               //used to do multithreating
using namespace std;
//userinterface thread
void userInterface(int cmdPos1, float cmdPos[]){
    string cmd = "";
    cout << "************************" << endl;
    cout << "* Quadrocopter control *" << endl;
    cout << "*       software       *" << endl;
    cout << "*                      *" << endl;
    cout << "*     version 0.1      *" << endl;
    cout << "*                      *" << endl;
    cout << "* Copyright J.H. Farr  *" << endl;
    cout << "************************" << endl << endl << endl;
    while(cmdPos1 != 4){
        cin >> cmd;
        if(cmd == "move"){
            cin >> cmdPos[0] >> cmdPos[1] >> cmdPos[2] >> cmdPos[3];
            cmdPos1 = 1;
            cout << endl << endl;
        } else if(cmd == "move+"){
            cin >> cmdPos[0] >> cmdPos[1] >> cmdPos[2] >> cmdPos[3];
            cmdPos1 = 2;
            cout << endl << endl;
        } else if(cmd == "land"){
            cmdPos1 = 3;
            cout << endl << endl;
        } else if(cmd == "exit"){
            cmdPos1 = 4;
            cout << endl;
        } else {
            cout << "invalid argument!!" << endl << endl;
        }
    }
}
//algorithm
void algorithm(float tele[], int cmdPos1, float cmdPos[]){
    while(cmdPos1 != 4){
        switch (cmdPos1){
            case 2:
            cout << "works!!";
            break;
            case 1:
            break;
            case 3:
            break;
        }
    }
}
//gets telemetrydata from mpu
void gettelempu(float tele[], int cmdPos1){
    while(cmdPos1 != 4){
    }
}
//gets height from ultrasonic sensor
void getheight(float tele[], int cmdPos1){
    while(cmdPos1 != 4){
    }
}
//main function
int main(){
    //telemetry data
    float tele[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    //what to do
    int cmdPos1 = 0;
    //where to go
    float cmdPos[4] = {0, 0, 0, 0};
    thread t1(userInterface, cmdPos1, cmdPos);
    thread t2(algorithm, tele, cmdPos1, cmdPos);
    thread t3(gettelempu, tele, cmdPos1);
    thread t4(getheight, tele, cmdPos1);
    t1.join();
    t2.join();
    t3.join();
    t4.join();
    return 0;
}
void gettelempu(float tele[], int cmdPos1)

此函数获取自己的cmdPos副本;在调用时,传递给它的值是0,函数永远不会更改该值,因此循环永远不会终止。algorithmgetheight也是如此。

为了在一个地方更改此参数的值并具有其他函数,请参阅更改函数必须通过引用获取值:

void gettelempu(float tele[], int& cmdPos1)

当创建线程时,您必须传递一个引用:

thread t3(gettelempu, tele, std::ref(cmdPos1));

但是等等,还有更多!不能保证在一个线程中对cmdPos1所做的更改对其他线程可见。为了确保这一点,让它成为原子。在main中,更改

int cmdPos1 = 0;

std::atomic<int> cmdPos1 = 0;

并将函数签名更改为采用std::atomic<int>而不是int:

void gettelempu(float tele[], std::atomic<int>& cmdPos1)