奇怪的线程执行顺序
Weird thread execution order?
我写了一个小程序来看看创建一个线程有多少开销。
程序如下(我写得很快,所以不是最好的):
#include <iostream>
#include <pthread.h>
void * lala(void * cake) {
int * hi = (int *)cake;
std::cout << *hi << 'n';
}
int main(void) {
pthread_t thread;
for (int i = 0;i < 10000;i = i + 1) {
pthread_create(&thread,0,lala,&i);
}
}
它基本上启动10000个线程并传递它们的线程号,每个线程输出它的线程号。
每次运行程序时输出都会改变,但是我注意到有一部分从未改变:
在输出的最后,我总是发现这样:
...
9994
9995
9996
9997
9998
9999
0
这意味着第一个线程最后完成…
那么,我的朋友们,有人对这一现象有什么可能的解释吗?
首先,将一个局部变量的地址传递给线程,这个地址是不断变化的。因此,当线程有时间读取它时,i
的内容已经被更改了。为什么你不能通过i
而不是&i
,其中变量只是4字节(即适合指针)?
其次,你不应该关心OS如何调度你的线程。
您的代码正在打印脏数据。没有内存屏障,所以数据实际上是垃圾。最重要的是,您不需要等待线程退出,因此很有可能在启动所有线程之前终止进程。为了达到(或多或少)你想要的,试着这样做:
#include <iostream>
#include <pthread.h>
void * lala(void * cake) {
int * hi = (int *)cake;
std::cout << *hi << 'n';
}
int main(void) {
int data[10000];
pthread_t t[sizeof (data) / sizeof (data[0])];
for (int i = 0; i < sizeof (data) / sizeof (data[0]); ++i)
{
data[i] = i;
}
for (int i = 0; i < sizeof (data) / sizeof (data[0]); ++i)
{
pthread_create(&t[i], 0, lala, &data[i]);
}
for (int i = 0; i < sizeof (data) / sizeof (data[0]); ++i)
{
pthread_join (t[i], NULL);
}
}
是的,CPU不是CUDA。创建线程是非常非常昂贵的。通常您最好使用单线程应用程序,除非您确实知道自己在做什么。我所看到的95%的多线程程序都在遭受线程饥饿而不是提高性能。
不管怎样,祝你好运!正如Ajay指出的那样,您正在传递一个指向本地变量的指针,该变量一直在更改,一旦它超出范围(当for结束时),对它的访问是未定义的行为。
无论如何,您应该将指向堆分配变量的指针传递给线程。你可以用malloc()
或new
。例如:
void * lala(void * cake) {
int hi = *(static_cast<int *>(cake));
delete cake; //we don't need it anymore, delete to avoid a leak
std::cout << hi << 'n';
}
int main(void) {
pthread_t thread;
for (int i = 0;i < 10000;i = i + 1) {
int * pie = new int;
*pie = i;
pthread_create(&thread,0,lala,pie);
}
}
这高度依赖于内核调度器的实现,也可能依赖于pthread库——并且线程的执行顺序永远无法保证。有很多优化是为了加快pthread的正常使用,而您的示例不是这样。
相关文章:
- QML按钮点击功能执行顺序
- C++ - scanf() 和 printf() 执行顺序不对
- 递归函数的执行顺序
- 运算符 new 的执行顺序和构造函数的参数
- 如何检查参数包是否具有执行顺序中的确切类型
- std::bind() 参数列表中函子的执行顺序(可能与函数参数的求值顺序无关)
- 了解递归函数的执行顺序
- OpenMP 4.5 任务依赖关系和执行顺序
- 通过调试来检查C 中单行表达式执行顺序的方法
- 遵循 C++ 中的构造函数执行顺序
- 联接线程如何影响主线程中的执行顺序?
- C COUT行为 /执行顺序
- 是定义的函数参数的内部执行顺序
- 强制执行执行顺序
- OpenGL计算着色器中线程的执行顺序
- 按执行顺序创建Pthread
- 逻辑操作员执行顺序
- 如何在使用 std::make_tuple 时避免构造函数的未定义执行顺序
- 提升::thread_specific_ptr/清理与退出执行顺序
- C++ 多线程:执行顺序