简体   繁体   English

std :: thread通讯问题

[英]std::thread communication issue

I am building a multithreaded application, but I've got a problem. 我正在构建一个多线程应用程序,但是我遇到了问题。 In the application I'm using a variable to communicate between the threads but it does not work. 在应用程序中,我使用一个变量在线程之间进行通信,但是它不起作用。 So when you type in exit the application does not stop executing. 因此,当您键入exit时 ,应用程序不会停止执行。

The code: 编码:

//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)

This function gets its own copy of cmdPos ; 该函数获取自己的cmdPos副本; at the time when it's called, the value passed to it is 0 , and the function never changes that value, so the loop never terminates. 在调用它时,传递给它的值为0 ,并且该函数永远不会更改该值,因此循环永远不会终止。 Same thing in algorithm and getheight . algorithmgetheight相同。

In order to change the value of this argument in one place and have other functions see that change the functions have to take the value by reference: 为了在一处更改此参数的值并具有其他功能,请参见更改功能必须通过引用获取值:

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

and when the thread is created you have to pass a reference: 创建线程时,您必须传递一个引用:

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

But wait, there's more! 但是,等等,还有更多! There's no guarantee that changes to cmdPos1 that are made in one thread will be visible to other threads. 不能保证在一个线程中对cmdPos1所做的更改将对其他线程可见。 To ensure this, make it atomic. 为了确保这一点,使其原子化。 In main , change main ,变化

int cmdPos1 = 0;

to

std::atomic<int> cmdPos1 = 0;

and change the function signatures to take an std::atomic<int> instead of an int : 并更改函数签名以采用std::atomic<int>而不是int

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM