pthread_join 导致奇怪的执行顺序 [英] pthread_join causes a weird execution sequence

查看:40
本文介绍了pthread_join 导致奇怪的执行顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的测试 C 程序如下:

#include #include #include __thread int var = 0;无效*工人(无效* arg);int main(){pthread_t pid1, pid2;pthread_create(&pid1, NULL, worker, (void*)0);pthread_create(&pid2, NULL, worker, (void*)1);printf("-----------1-----------\n");pthread_join(pid1, NULL);睡眠(1);printf("-----------2-----------\n");pthread_join(pid2, NULL);返回0;}空*工人(空* arg){int idx = (int)arg;国际我;for (i = 0; i <10; ++i) {printf(线程:%d ++var = %d\n",身份证,++变量);}}

然后我编译如下:

$ gcc -g -Wall -pthread 1.c -lpthread -o 测试1.c:在函数‘worker’中:1.c:27:15: 警告:从指针转换为不同大小的整数 [-Wpointer-to-int-cast]27 |int idx = (int)arg;|^1.c:35:1:警告:控制到达非空函数的结尾[-Wreturn-type]35 |}|^

运行结果如下:最后一行1秒后出来.但我不明白为什么 "thread: 1" 出现在 "thread: 0" 之前?

$ ./test-----------1-----------线程:1 ++var = 1线程:1 ++var = 2线程:1 ++var = 3线程:1 ++var = 4线程:1 ++var = 5线程:1 ++var = 6线程:1 ++var = 7线程:1 ++var = 8线程:1 ++var = 9线程:1 ++var = 10线程:0 ++var = 1线程:0 ++var = 2线程:0 ++var = 3线程:0 ++var = 4线程:0 ++var = 5线程:0 ++var = 6线程:0 ++var = 7线程:0 ++var = 8线程:0 ++var = 9线程:0 ++var = 10-----------2-----------

解决方案

为什么线程:1"?出现在线程:0"之前?

只是线程 1 先获得 CPU 时间,速度太快,可以打印所有内容.

最可能发生的情况是 main() 有 CPU 时间,然后 main() 运行 pthread_join,在这种情况下它会产生处理器时间和调度程序开始工作.然后调度程序决定将 CPU 时间分配给线程 1 - 可能是最后一个,任意选择.该线程足够快,可以在调度程序能够重新调度 CPU 时间之前将其全部打印出来.

线程彼此之间没有顺序 - 您不能期望任何类型的顺序,除了 printf 输出不应混合,即 printf 本身是线程安全的.一个线程在另一个线程之前打印与任何其他结果一样没有顺序.

<块引用>

警告:从指针转换为不同大小的整数

执行 (uintptr_t)arg; 使警告静音.

<块引用>

警告:控制到达非空函数的结尾

这是一个非常严重的警告,会导致未定义的行为.特别是,最近我探索了这个确切的问题如何导致 无限循环 与您的代码非常相似.在函数末尾添加return NULL;.

This is my test C program as below:

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

__thread int var = 0;

void* worker(void* arg);

int main()
{
    pthread_t pid1, pid2;

    pthread_create(&pid1, NULL, worker, (void*)0);
    pthread_create(&pid2, NULL, worker, (void*)1);

    printf("-----------1----------\n");
    pthread_join(pid1, NULL);
    sleep(1);
    printf("-----------2----------\n");
    pthread_join(pid2, NULL);

    return 0;
}

void* worker(void* arg)
{
    int idx = (int)arg;
    int i;

    for (i = 0; i < 10; ++i) {
        printf("thread: %d  ++var = %d\n",
            idx,
            ++var);
    }
}

And then I compile it as below:

$ gcc -g -Wall -pthread 1.c -lpthread -o test
1.c: In function ‘worker’:
1.c:27:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   27 |     int idx = (int)arg;
      |               ^
1.c:35:1: warning: control reaches end of non-void function [-Wreturn-type]
   35 | }
      | ^

Run result as below: the last line comes out 1 second later. But I cannot understand why "thread: 1" comes before "thread: 0"?

$ ./test 
-----------1----------
thread: 1  ++var = 1
thread: 1  ++var = 2
thread: 1  ++var = 3
thread: 1  ++var = 4
thread: 1  ++var = 5
thread: 1  ++var = 6
thread: 1  ++var = 7
thread: 1  ++var = 8
thread: 1  ++var = 9
thread: 1  ++var = 10
thread: 0  ++var = 1
thread: 0  ++var = 2
thread: 0  ++var = 3
thread: 0  ++var = 4
thread: 0  ++var = 5
thread: 0  ++var = 6
thread: 0  ++var = 7
thread: 0  ++var = 8
thread: 0  ++var = 9
thread: 0  ++var = 10
-----------2----------

解决方案

why "thread: 1" comes before "thread: 0"?

It's just that the thread 1 gets CPU time first and is soo fast that is able to print it all.

Most probably what happens, is that main() has CPU time, then main() runs pthread_join, in which case it yields processor time and scheduler kicks in. Then the scheduler decides to give CPU time to thread 1 - probably the last one, an arbitrary choice. The thread is fast enough to print it all before the scheduler is able to re-schedule CPU time.

The threads are unsequenced with each other - you can't expect any kind of order, except that printf outputs should not mix, i.e. printf itself is thread safe. One thread printing before the other is as unsequenced as any other result.

warning: cast from pointer to integer of different size 

Do (uintptr_t)arg; to silence the warning.

warning: control reaches end of non-void function

It is a very serious warning and results in undefined behavior. In particular, lately I explored how this exact problem may result in an endless loop with very similar code to yours. Add return NULL; on the end of the function.

这篇关于pthread_join 导致奇怪的执行顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆