线程和非线程函数调用的执行顺序是啥?

Posted

技术标签:

【中文标题】线程和非线程函数调用的执行顺序是啥?【英文标题】:what is the execution order of a threaded and non-threaded function call?线程和非线程函数调用的执行顺序是什么? 【发布时间】:2010-08-24 07:22:03 【问题描述】:

我编写了一个简单的控制台应用程序只是为了尝试 boost::thread,顺便说一下,我是一个多线程新手。这是代码

#include <iostream>
#include <boost/thread/thread.hpp>
#include <windows.h>

using namespace std;

void Avg(double * Src, double *Dst, int Per, int Len, string& s )

    LARGE_INTEGER s1,s2,f;
    QueryPerformanceFrequency(&f);
    QueryPerformanceCounter(&s1);
    for(int i = Per-1; i < Len ; i++)
    
        double a = 0;
        for(int j = i; j > i-Per ; j--)
            a += Src[j];
        Dst[i] = a / Per;
           
    QueryPerformanceCounter(&s2);
   cout << double(s2.QuadPart-s1.QuadPart)/f.QuadPart*1000 << " ms : "+s << endl;


int main(int argc, char* argv[])

    int L = 200000;
    double  * a = new double[L], *b = new double[L] , *c = new double[L];
    for(int i =0; i < L;i++)
    
        a[i] = i+2;
    
    int x = 10000;
    boost::thread bAvg(Avg,a,b,x,L,string("T"));
    LARGE_INTEGER s1,s2,f;
    QueryPerformanceFrequency(&f);
    QueryPerformanceCounter(&s1);

    Avg(a,c,x,L,string("N")); // line 1
    bAvg.join(); // line 2

    QueryPerformanceCounter(&s2);
    cout << double(s2.QuadPart-s1.QuadPart)/f.QuadPart*1000 << " ms : Total" << endl;


    delete []a;
    delete []b;
    delete []c;

    system("PAUSE");
         return 0;

该代码的输出是

6621.1 毫秒:N 6635.28 毫秒:T 6638.29 毫秒:总计 按任意键继续 。 . .

但是当我更改第 1 行和第 2 行的顺序时,输出变为:

6274.57 毫秒:T 6250.56 毫秒:N 12531.3 毫秒:总计 按任意键继续 。 . .

在情况 1 中,bAvg.join() 会在 Avg 触发之后和完成之前触发。我认为案例 1 和案例 2 的结果会是相反的。我认为这与线程的执行顺序有关。

编辑: 实际上,我正计划为交易目的编写应用程序。例如,我将为单个股票的每个即将到来的信号创建至少 10 个计算线程。信号将通过 tcp 连接接收。但是如果主执行线程等待其他子线程的完成,那么很容易错过一个信号,因为主线程是空闲的。我应该如何处理信号并运行计算线程?

【问题讨论】:

鉴于您提出的问题,您最好退后一步,花一些时间真正了解线程。如果您不太了解正在发生的事情,它是通往整个世界的错误和痛苦的门户,并且您可能不希望在交易代码中出现这种情况。您现在可以编写一个单线程应用程序吗?你证明你需要多个线程吗?无论如何,由于通信成本,天真的线程应用程序通常最终会比它们的非线程应用程序慢。 @chrispy:事实上我的单线程应用程序已经准备好了。但我担心的是,如果在计算刚接收到的信号期间接收到信号怎么办。我想出的答案只是打开另一个线程并处理另一个 cpu 内核上的信号(如果可用)。我的回答错了吗? 一种可能适合您的简单设计:让一个线程处理传入信号并将它们排队等待处理,另一个线程将它们拉出队列并按顺序处理它们。不过,也许您可​​以让 tcp 库为您进行排队?即,如果可能,请留下信号,直到您准备好处理它们。我不知道您的 tcp 库的详细信息。这将使您免受线程细节的影响。 【参考方案1】:

在第一种情况下,order 可能同时是 N T 和 T N,因为这两个函数是并行执行的。在第二种情况下,输出只能是 T N,因为第一个函数 (T) 必须在第二个函数 (N) 开始之前完成。 bAvg.join 表示“等待线程函数退出”。

【讨论】:

真的是“等待线程函数退出”的意思吗?如果线程被强制终止,线程函数是否真的退出?这不是一个反问的问题,我真的不知道。 Space_C0wb0y:boost线程在线程函数执行return语句时结束,或者通过中断点结束。 join 运算符等待它们中的任何一个,并且仅在底层 OS 线程结束时返回。【参考方案2】:

当第 1 行和第 2 行交换时,您首先在另一个线程中触发 bAvg 并等待它完成。然后只有你在主线程上启动bAvg。这就是为什么在这种情况下总时间加倍的原因:您的计算是按顺序完成的。

【讨论】:

所以你是说 bAvg 被解雇了两次? @bahadir:不,程序有两个线程,主执行线程和bAvg。在第一种情况下,两个线程都在并行执行工作,而在第二种情况下,您让主线程等待(在join 调用中)等待bAvg 工作的完成,然后再执行它的工作份额。【参考方案3】:

当您创建boost::thread 时,会立即启动一个新线程,但这并不意味着通常处理线程调度的操作系统会立即切换到该线程。这可能随时发生。例如,尝试在创建线程后立即插入此行:

boost::this_thread::yield()

这使得当前线程(在这种情况下是您的主线程)产生剩余的 CPU 时间以支持其他线程,例如 bAvg(但不一定,这完全取决于操作系统调度程序)。

通常,除非您使用同步,否则永远不要对不同线程或进程中的执行顺序做出任何假设。

【讨论】:

以上是关于线程和非线程函数调用的执行顺序是啥?的主要内容,如果未能解决你的问题,请参考以下文章

三个线程顺序输出

关于线程的执行顺序,可能真的只是你以为的你以为

如何确保三个线程顺序执行

有三个线程,怎么让他们按顺序执行?

js能不能通过返回值顺序执行

MFC中如何让多线程按先后顺序执行,第一个来的先执行,以后按先后到达的顺序执行