在多线程程序中执行的线程的C阶

时间:2018-07-19 05:04:42

标签: c multithreading pthreads

我对线程编码还很陌生,所以我正在做一个练习,我在网上找到了,该练习要求这样的事情:

编写一个程序hellomany.c,它将创建N个在命令行中指定的线程,每个线程都会打印出一个hello消息及其自己的线程ID。若要查看线程的执行方式是如何交错的,请使主线程每创建4或5个线程休眠1秒。您的代码输出应类似于:

   I am thread 1. Created new thread (4) in iteration 0...
   Hello from thread 4 - I was created in iteration 0
   I am thread 1. Created new thread (6) in iteration 1...
   I am thread 1. Created new thread (7) in iteration 2...
   I am thread 1. Created new thread (8) in iteration 3...
   I am thread 1. Created new thread (9) in iteration 4...
   I am thread 1. Created new thread (10) in iteration 5...
   Hello from thread 6 - I was created in iteration 1
   Hello from thread 7 - I was created in iteration 2
   Hello from thread 8 - I was created in iteration 3
   Hello from thread 9 - I was created in iteration 4
   Hello from thread 10 - I was created in iteration 5
   I am thread 1. Created new thread (11) in iteration 6...
   I am thread 1. Created new thread (12) in iteration 7...
   Hello from thread 11 - I was created in iteration 6
   Hello from thread 12 - I was created in iteration 7

我设法编写的代码是:

#include <stdio.h>       
#include <stdlib.h>
#include <pthread.h>     

void* PrintHello(int iteration)
{
    printf("Hello from thread %u - I was created in iteration %d \n", 
    pthread_self(), iteration);
    pthread_exit(NULL);                 
}

int main(void)
{
    int        rc;                
    pthread_t  thread_id;             
    int        tidMain;
    int        n, i;

    tidMain = pthread_self();

    printf("How many threads are there to be created?\n");
    scanf("%d", &n);

    for(i = 1; i <= n; i++) {

        pthread_t thread_id;
        rc = pthread_create(&thread_id, NULL, PrintHello, i);
        printf("I am thread %u. Created new thread (%u) in iteration %d\n", 
        tidMain, thread_id, i);
        if(rc)                             
        {
            printf("\n ERROR: return code from pthread_create is %d \n", rc);
            exit(1);
        }
        if((i % 5) == 0) {
            sleep(1);
        }

    }

    pthread_exit(NULL);
}

该程序确实打印了我想要的内容,甚至休眠并“破坏”了每5个线程创建的创建内容。仍然,我不知道为什么,但是当每个创建的线程要在我想要的5线程打印条纹中被执行时(在主线程通知它们已经创建之后), “打招呼”的线程是最后创建的线程。我从控制台获得的信息,即当我要求它创建8个线程时,是这样的:

I am thread 3075630848. Created new thread (3075627840) in iteration 1
I am thread 3075630848. Created new thread (3067235136) in iteration 2
I am thread 3075630848. Created new thread (3058842432) in iteration 3
I am thread 3075630848. Created new thread (3050449728) in iteration 4
I am thread 3075630848. Created new thread (3042057024) in iteration 5
Hello from thread 3042057024 - I was created in iteration 5 
Hello from thread 3050449728 - I was created in iteration 4 
Hello from thread 3058842432 - I was created in iteration 3 
Hello from thread 3067235136 - I was created in iteration 2 
Hello from thread 3075627840 - I was created in iteration 1 
I am thread 3075630848. Created new thread (3032480576) in iteration 6
I am thread 3075630848. Created new thread (3024087872) in iteration 7
I am thread 3075630848. Created new thread (3015695168) in iteration 8
Hello from thread 3015695168 - I was created in iteration 8 
Hello from thread 3024087872 - I was created in iteration 7 
Hello from thread 3032480576 - I was created in iteration 6

据我了解,它首先执行创建的最后一个线程。为什么会这样?我可以让它执行第一个创建的第一个吗?

顺便说一句:我正在Ubuntu上运行

3 个答案:

答案 0 :(得分:1)

这是关于并发编程的要点。您永远无法对线程执行的顺序进行任何假设。例如,我得到以下输出:

I am thread 639280960. Created new thread (630781696) in iteration 1
Hello from thread 630781696 - I was created in iteration 1
I am thread 639280960. Created new thread (622388992) in iteration 2
Hello from thread 622388992 - I was created in iteration 2
I am thread 639280960. Created new thread (613996288) in iteration 3
Hello from thread 613996288 - I was created in iteration 3
I am thread 639280960. Created new thread (536868608) in iteration 4
Hello from thread 536868608 - I was created in iteration 4
I am thread 639280960. Created new thread (526280448) in iteration 5
Hello from thread 526280448 - I was created in iteration 5
I am thread 639280960. Created new thread (517887744) in iteration 6
I am thread 639280960. Created new thread (509495040) in iteration 7
Hello from thread 509495040 - I was created in iteration 7
I am thread 639280960. Created new thread (501102336) in iteration 8
Hello from thread 501102336 - I was created in iteration 8
Hello from thread 517887744 - I was created in iteration 6

如果再次运行它,可能会得到不同的输出。自己尝试一下!

Wikipedia Article about Concurrent computing说:

  

在并发系统中执行任务的确切时间   取决于调度,任务不一定总是执行   同时。例如,给定两个任务T1和T2:

     
      
  • T1可以在T2之前执行并结束,反之亦然(顺序和顺序)

  •   
  • T1和T2可以交替执行(串行和并发)

  •   
  • T1和T2可以在同一时间(并行和并发)同时执行

  •   

我建议您阅读一些有关并发和并行性的基本文章或文献。

答案 1 :(得分:1)

这是一个并发程序。如果您多次运行程序,则即使在同一主机中,顺序也会有所不同。

顺便说一句,也许最好在编码之前先查看pthread API。

对于pthread_create()

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);

第三个参数是void *(*start_routine)(void *)而不是void *(start_routine)(int),第四个参数是void *而不是int

答案 2 :(得分:1)

执行线程的顺序不确定。如果您需要特定的命令,则必须使用锁,互斥锁和条件来命令其执行以符合您的要求。

您看到的顺序是由硬件和内核(有时是随机性)引起的。我假设您只有一个单核CPU,否则输出将毫无意义。创建线程时,内核只需调度线程在以后运行,并继续执行主线程。因此,您会收到有关所有5个线程创建的消息。仅当主线程进入睡眠状态时,内核才会切换到准备运行的下一个线程。好像是FILO(先入后出)。这恰好是您硬件上的版本中的内核恰好要做的。随时可以更改。

另一方面,

pOwl似乎具有多个核心。因此,当主线程创建线程时,其他内核已经执行了它们。或者他只是拥有不同的内核。