c++ - 线程在 while 循环中卡住

标签 c++ multithreading

当在 GCC 中编译发布时,我的算法中的线程出现了奇怪的行为。即使 while 条件发生变化,线程也不会离开等待循环,就好像刚刚死了一样。

我注意到的另一件事是,如果将 std::this_thread.sleep_for(10ms) 插入到等待循环中,它可以正常工作,或者如果我编译为调试,它也可以正常工作。

以下(伪)代码是代码的简化版本。

bool some_data_ready = false;
bool lets_plot_data = false;

bytearray packets; // a dynamic bytearray that holds a stream of packets

void decode(){
    while(1){
        if(packets.size() > 200){ // packets has data to be decoded

            while (lets_plot_data) { //waiting loop
                /* on the second run it gets stuck here becuse thread 1 dont
                 * leave its locking loop even if lets_plot_data changes
                 */
                //this_thread.sleep_for(10ms);
            }

            for(int i = 0;i< packets.size();++i){
                if(packets.at(i) == 255){
                    if(packets.at(i+15) == 200){
                        //checks if packet has a start and an end
                        if(packets.at(14) == xor_checksum(packets.at(i))){
                            //packet is valid if calculated checksum is equal to the packet checksum
                            some_data_ready = true;
                            plot_data.push(packets.mid(i,15)); // copy a section starting at i len 15
                            // gets a packet and push it do be plotted
                        }
                    }
                }
            }

            if(some_data_ready){
                lets_plot_data = true;
                some_data_ready = false;
            }
        }
    }
}

void plot(){
    while(1){
        while (!lets_plot_data) { //thread dont leave here even if lets_plot_data changes
            //this_thread.sleep_for(10ms);
        }
        graph.plot(plot_data); // not relevant, plots data at a graph
        lets_plot_data = false;
    }
}

std::thread* thread0;
std::thread* thread1;
std::thread* thread2;


int main(void){
    thread0 = new std::thread(data); // gets data to be decoded (stream of ubytes containing packets)
    thread1 = new std::thread(plot); // plot decoded data
    thread2 = new std::thread(decode); // decodes data to be ploted

    while(1){
        //"gui loop"
    }

    return 0;
}

如果想知道,我的 GCC 发布标志是

-Ofast -msse -fomit-frame-pointer -fmodulo-sched -fmodulo-sched-allow-regmoves -fgcse-sm -fgcse-las -fgcse-after-reload -funsafe-loop-optimizations -flive-range-shrinkage -fsched-spec-load-dangerous -fsched2-use-superblocks -floop-nest-optimize -floop-parallelize-all -ftree-parallelize-loops=8 -fprefetch-loop-arrays -ffinite-math-only -march=native -mtune=native -mfpmath="387+sse" -std=c++17 -lstdc++ -static

但它也不适用于 -O2

并且与 -g -Og 一起工作得很好,尽管它看起来很奇怪

感谢您的关注。

最佳答案

你的标志有一个明显的竞争条件:你在执行 plot() 的线程和执行 的线程中读取和写入 lets_plot_data decode() 并且没有什么能阻止这同时发生。

您需要将这些标志声明为原子的:

    atomic<bool> some_data_ready { false };
    atomic<bool> lets_plot_data { false };

如果您还不熟悉此类问题,我建议您观看 this video from Herb Sutter .

关于c++ - 线程在 while 循环中卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46506501/

相关文章:

c++ - 确定 CE 上的 XAML 解析错误位置

java - 如何为多线程程序设置环境变量?

c# - Task.Factory.StartNew() 是否保证使用调用线程之外的另一个线程?

java - 通过多线程的并发方法

c++ - 如何在 PC/Visual C++ 上查明指针是否在堆栈上

C++ 线程错误 : no type named ‘type’ MINGW

c++ - 为什么 C++ 字符串迭代器不检查错误?

c++ - 在 OpenCV 中将 HSV 转换为 RGB 失败

python - 除非程序崩溃,否则子 multiprocessing.Process 没有打印输出

java - Eclipse (Helios) 调试器 - 在 Debug模式和运行模式下获得不同的结果