开发者

Weird thread execution order?

I wrote a small program to see the amount of overhead there is to create a thread.

Here is the program (I wrote it quickly so it isn't the best):

#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);
 }
}

It basically launches 10000 threads and passes them their thread number, and each thread outputs its number.

The output changes each time I run the program, however I noticed that there was one part that never changed:

At the end of the output, I always find this:

...
9994
9995
9996
9997
9998
9999
0

Which means that the first thread finishes last...

So, my friends, does anyone have a possible explanation for this phenomenon?


First thing, you are passing the address-of a local variable to the thread, which is constantly changing. So, when the thread gets time to read it, the content of i would already be changed. Why can't you just pass i instead of &i, where variable is just of 4-bytes (i.e. fits in pointer)?

Secondly, you shouldn't be concerned how OS schedules your threads.


Your code is printing dirty data. There is no memory barrier so data is literally garbage. On top of that, you do not wait for threads to exit, so there is a big chance that the process will be terminated before you fire up all threads. To achieve (more or less) what you want, try something like this:

#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);
 }

}

And yeah, CPU is not CUDA. Creating threads is very, very expensive. Usually you better off with a single-threaded application unless you really know what you are doing. 95% of multi-threaded programs that I saw are suffering from thread starvation rather than gaining performance.

Anyway, good luck!


As Ajay pointed out, you are passing a pointer to a local variable that gets changed all the time and once it gets out of scope (when the for finishes) the access to it is undefined behavior.

Anyway, you should pass a pointer to a heap-allocated variable to your thread. You can get that with a malloc() or new. For example:

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);
    }
}


This is highly dependent on the kernel scheduler implementation and also possibly the pthread library - and ordering of execution of threads is never guaranteed. There are lots of optimizations done to speed up normal uses of pthreads, which your example is not.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜