简体   繁体   English

为什么我创建的线程没有按顺序打印?

[英]Why are my threads I created not printed in order?

I have this program: 我有这个程序:

void *func(void *arg) {
    pthread_mutex_lock(&mutex);
    int *id = (int *)arg;

    printf("My ID is %d\n" , *id);
    pthread_mutex_unlock(&mutex);
}

int main() {
    int i;
    pthread_t tid[3];

    // Let us create three threads
    for (i = 0; i < 3; i++) {
        pthread_create(&tid[i], NULL, func, (void *)&i);
    }

    for (i = 0; i < 3; i++) {
        pthread_join(tid[i], NULL);
    }

    pthread_exit(NULL);
    return 0;
}

I expected it to output this: 我希望它能输出以下内容:

My ID is 0
My ID is 1
My ID is 2

But instead I get random output, such as this: 但是我得到的是随机输出,例如:

My ID is 0
My ID is 0
My ID is 2

Since I already added mutex lock, I thought it would solve the problem. 由于我已经添加了互斥锁,所以我认为这可以解决问题。 What else did I do wrong? 我还做错了什么? Is this related to race condition? 这与种族状况有关吗?

Here id points to the same variable i in main for all the threads. 在此, id指向所有线程的main中相同的变量i

int *id = (int *)arg;

printf("My ID is %d\n" , *id);

But the variable i is constantly being update by the two for -loops in main behind the threads back. 但是变量i经常被线程后面的main的两个for -loops更新。 So before the thread reaches the point of printf , the value of i , and therefore also the value of *id , may have changed. 因此,在线程到达printf的点之前, i的值以及*id的值可能已经更改。

There are a few ways to solve this. 有几种解决方法。 The best way depends on the use case: 最佳方法取决于用例:

  1. Wait in main until the thread signals that it has made a copy of *id before modifying i or letting it go out of scope. 在修改线程i或使其超出范围之前,先在main等待线程发出信号,表明它已复制*id
  2. Declare and initialize an array, int thread_id[] , and create the threads like this: pthread_create(&tid[i], NULL, func, &thread_id[i]); 声明并初始化一个数组int thread_id[] ,然后像下面那样创建线程: pthread_create(&tid[i], NULL, func, &thread_id[i]);
  3. malloc some memory and and initialize it with a copy of i : malloc一些内存并使用i的副本对其进行初始化:

     int *thread_id = malloc(sizeof(*thread_id)); *thread_id = i pthread_create(&tid[i], NULL, func, thread_id); 

    Just don't forget to free your memory int the thread when you are finished using it. 只是不要忘记在使用完线程后将其free到线程中。 Or in main if the thread fails to start. 或者在main线程中,如果线程无法启动。

  4. If i fits in a void * can pass its content directly as a parameter to the thread. 如果i适合一个void *可以将其内容直接作为参数传递给线程。 To make sure it fits, you can declare it as intptr_t rather than int (We basicly abuse the fact that pointers are nothing more than magic integers) : 为了确保它合适,可以将其声明为intptr_t而不是int (我们基本上滥用了指针不过是魔术整数这一事实):

     void *func(void *arg) { pthread_mutex_lock(&mutex); // Here we interpret a pointer value as an integer value intptr_t id = (intptr_t )arg; printf("My ID is %d\\n" , (int)id); pthread_mutex_unlock(&mutex); } int main() { intptr_t i; pthread_t tid[3]; // Let us create three threads for (i = 0; i < 3; i++) { // Here we squeeze the integer value of `i` into something that is // supposed to hold a pointer pthread_create(&tid[i], NULL, func, (void *)i); } for (i = 0; i < 3; i++) { pthread_join(tid[i], NULL); } // This does not belong here !! // pthread_exit(NULL); return 0; } 

Nope, no race conditions involved. 不,不涉及比赛条件。 (my b) There can be a race condition on i because all threads access it. (my b)i上可能存在竞争状况,因为所有线程都访问它。 Each thread gets started with a pointer to i. 每个线程都以指向i的指针开始。 However, the main problem is that there is no guarantee that the thread will start and run the critical section while i holds the value you expect, in an order that you expect. 但是,主要问题是,不能保证在我按您期望的顺序保存您期望的值时,线程将启动并运行关键部分。

I'm assuming you declared the variable mutex globally and called pthread_mutex_init() somewhere to initialize it. 我假设您全局声明了变量mutex ,并在某处调用pthread_mutex_init()进行了初始化。

Mutexes are great to allow only one thread to access a critical section of code at a time. 互斥体很棒,一次允许一个线程访问关键的代码部分。 So the code as you've written creates all three threads to run in parallel, but only lets one thread at a time run the following code. 因此,您编写的代码创建了所有三个线程以并行运行,但一次只允许一个线程运行以下代码。

int *id = (int *)arg;

printf("My ID is %d\n" , *id);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM