线程和非线程函数调用的执行顺序是啥?
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
(但不一定,这完全取决于操作系统调度程序)。
通常,除非您使用同步,否则永远不要对不同线程或进程中的执行顺序做出任何假设。
【讨论】:
以上是关于线程和非线程函数调用的执行顺序是啥?的主要内容,如果未能解决你的问题,请参考以下文章