• linux下的线程thread


    何为线程?

    线程是一种轻量级的进程,一个进程至少包含 1 个线程,也可以包含多个线程,所有线程共享进程的资源,各个线程也可以拥有属于自己的私有资源。其实,进程仅负责为各个线程提供所需的资源,真正执行任务的是线程,而不是进程。

    如何创建一个线程?

    POSIX(可移植操作系统接口) 标准中规范了与多线程相关的系统接口。我们在 Linux 系统上编写多线程程序,只需在程序中引入头文件,调用该文件中包含的函数即可实现多线程编程, 头文件中只包含各个函数的声明部分,具体实现位于 libpthread.a 库中,在编译的时候需要链上这个静态库。

    线程创建的过程,就是先调用pthread_create创建一个新线程,然后pthread_join,等待线程处理,最终就是终止线程。

    我们先来学习一下几个关键的函数,man一下pthread_create这个函数,可以看到,这个函数有四个入参和一个返回int型返回值

    int pthread_create(

            pthread_t *thread,

            const pthread_attr_t *attr,

            void *(*start_routine) (void *),

            void *arg);

    参数1:放入一个线程标识符的地址

    参数2:是对线程属性的修改,一般不修改,直接给null,pthread_create() 函数会采用系统默认的属性值创建线程。

    参数3:以函数指针的方式指明新建线程需要执行的函数

    参数4:线程处理函数的入参,要传入处理的参数,可以给null

    返回值:创建成功则返回0,非0就表示不成功。


    再man一下pthread_join这个函数,他是两个参数,返回值也是一个int型

    int pthread_join(pthread_t thread, void **retval);

    参数1:要等待的线程的线程标识符

    参数2:保存线程处理函数的返回值,注意是二级指针

    返回值: 返回0表示成功,非0表示不成功

    pthread_join() 函数会一直阻塞调用它的线程,直至目标线程执行结束(接收到目标线程的返回值),阻塞状态才会解除。并且一个线程执行结束的返回值只能由一个 pthread_join() 函数获取,当有多个线程调用 pthread_join() 函数获取同一个线程的执行结果时,哪个线程最先执行pthread_join() 函数,执行结果就由那个线程获得,其它线程的 pthread_join() 函数都将执行失败。


    此处给出一个示例代码,读者可以参考学习

    1. #include <stdio.h>
    2. #include <pthread.h>
    3. //定义线程要执行的函数,
    4. //arg为接收线程传递过来的数据
    5. void *Thread1(void *arg)
    6. {
    7. printf("hello world\n");
    8. return "thread1 finish";
    9. }
    10. void* Thread2(void* arg)
    11. {
    12. printf("hi world\n");
    13. return "thread2 finish";
    14. }
    15. int main()
    16. {
    17. int res; //存放创建是否成功的返回值
    18. pthread_t mythread1, mythread2; //定义两个线程的标识符
    19. void* thread_result; //定义一个void *的指针,后面可以给他赋任意类型的指针
    20. /*创建线程(create)
    21. &mythread:要创建的线程
    22. NULL:不修改新建线程的任何属性
    23. ThreadFun:新建线程要执行的任务
    24. NULL:不传递给 ThreadFun() 函数任何参数
    25. 返回值res为 0 表示线程创建成功,反之则创建失败。
    26. */
    27. res = pthread_create(&mythread1, NULL, Thread1, NULL);
    28. if (res != 0)
    29. {
    30. printf("线程创建失败\n");
    31. return -1;
    32. }
    33. res = pthread_create(&mythread2, NULL, Thread2, NULL);
    34. if (res != 0)
    35. {
    36. printf("线程创建失败\n");
    37. return -1;
    38. }
    39. /*
    40. 等待线程(join)
    41. mythread*:指定等待的线程
    42. &thead_result:接收 ThreadFun() 函数的返回值,或者接收 pthread_exit() 函数指定的值
    43. 返回值 res 为 0 表示函数执行成功,反之则执行失败。
    44. */
    45. res = pthread_join(mythread1, &thread_result);
    46. //输出线程执行完毕后返回的数据
    47. printf("%s\n", (char*)thread_result);
    48. res = pthread_join(mythread2, &thread_result);
    49. printf("%s\n", (char*)thread_result);
    50. printf("main thread finish\n");
    51. return 0;
    52. }

    编译的时候需要加上-lpthread这个静态库,才能编译通过。(关于静态库和动态库的知识可以看我另一篇博文,链接如下)

    编译的命令如下,可以看到运行的结果,没有问题。

    有一个需要注意的点,上面这个程序,这个进程中,我们虽然自己只是创建了两个线程,但实际上是有三个线程,另外一个是本就存在的主线程,就像文章开头所说的,进程不办事,办事的都是线程,所以一个进程,最初肯定是有一个线程在的。

    从程序中还可以看出的是, pthread_create() 函数成功创建的线程会自动执行指定的函数,不需要手动开启,此外,为了防止主线程提前退出,而没来得及执行其他线程,我们一般会在主线程中加上sleep延时一下。

    终止线程执行

    终止线程执行的办法呢,有三种。

    第一种自动终止,就是不去人为干预,线程运行完了自己就退出了,

    第二种pthread_exit(),其实和return有点类似,但是pthread_exit()是专门用来退出一个线程的,不会影响其它线程的执行,而return是会影响到其他线程的,就比如在主线程中用了return,那整个程序就都退出了,包括其他的线程。使用的方法如下。

    1. void *ThreadFun(void *arg)
    2. {
    3. //终止线程的执行
    4. pthread_exit("线程终止成功"); //返回的字符串存储在常量区,并非当前线程的私有资源
    5. printf("线程终止失败");//此语句不会被线程执行
    6. }

    第三种pthread_cancel()其实是一种信号终止,他具体是通过一个线程向另一个线程(需要在同一个进程内)发送终止信号来实现终止线程的,使用的方法就是在pthread_cancel()的括号中加上想要终止的线程标识符就行。

    1. int pthread_cancel(pthread_t thread);
    2. //返回值是0说明终止成功

  • 相关阅读:
    Java虚拟机(JVM)-- Dump内存快照
    GIS 数据结构BSP树
    java毕业设计电子存证系统(附源码、数据库)
    ElasticSearch从入门到精通(一)
    信奥 提高篇 高级数据结构 RMQ问题 ST算法(2022.11.02)
    asp.net 在线音乐网站系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
    vscode离线安装ssh插件(本机和服务器都离线)
    TypeScript 学习笔记
    golang 摄像头截图命令版本
    Andriod Studio小游戏
  • 原文地址:https://blog.csdn.net/qq_45570844/article/details/126805476