• Linux编程基础——线程概述


    有的时候,我们需要在一个基础中同时运行多个控制流程。例如:一个图形界面的下载软件,在处理下载任务的同时,还必须响应界面的对任务的停止,删除等控制操作。这个时候就需要用到线程来实现并发操作。

    和信号处理函数的控制在处理完信号之后就结束不同的时,而多线程的控制流程可以长期并存,操作系统会在各线程之间调度和切换,就像在多个进程之间调度和切换一样,但创建线程开销要比进程小得多。因此,线程往往也被称作轻量级的进程。

    由于同一进程的多个线程共享同一地址空间,数据段是共享的,如果定义一个全局变量,在各线程中都可以访问到。但有,些资源依然是每个线程各有一份的:

    • 线程id
    • 上下文,包括各种寄存器的值、程序计数器和栈指针
    • 栈空间
    • errno变量
    • 信号屏蔽字
    • 调度优先级

    我们一般用到的是由POSIX标准定义的线程库函数,称为POSIX thread或者pthread。在Linux上线程函数位于libpthread共享库中,因此在编译时要加上-lpthread选项。

    创建线程

    在POSIX库中,创建线程是通过函数实现的,它的声明如下:

        #include <pthread.h>

        int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

                            void *(*start_routine) (void *), void *arg);

    它有四个参数,

    • 第一个参数thread为创建后的线程标识符的指针。
    • 第二个参数attr为线程属性,可选为PTHREAD_CREATE_DETACHED(分离线程)和 PTHREAD _CREATE_JOINABLE(非分离线程),一般是直接用NULL。
    • 第三个参数start_routine为线程的运行函数
    • 第四个参数arg为线程运行函数的参数
    • 创建成功时,返回0,失败是返回错误码。这个和其它的系统函数失败返回-1,由errno返回错误码不大一样。

    一个简单的示例如下:

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

        void* thr_fn(void *arg)
        {
            pid_t pid = getpid();
            pthread_t tid = pthread_self();

            printf("%s pid %u tid %u (0x%x)\n", arg, (unsigned int)pid,    (unsigned int)tid, (unsigned int)tid);

            return NULL;
        }

        int main(void)
        {
            pthread_t ntid = {0};

            int err = pthread_create(&ntid, NULL, thr_fn, (void*)"new thread: ");
            if (err != 0)
            {
                fprintf(stderr, "can't create thread: %s\n", strerror(err));
                exit(1);
            }

            void *tret;
            pthread_join(ntid, &tret);
            printf("thread exited\n");

            return 0;
        }

    当我们编译这段程序时,会发现如下错误:

        tianfang@linux-k36c:/mnt/share/test> make
        make: Warning: File `Makefile' has modification time 0.48 s in the future
        g++ -o run main.o
        main.o: In function `main':
        /mnt/share/test/main.cpp:20: undefined reference to `pthread_create'
        collect2: error: ld returned 1 exit status
        make: *** [run] Error 1
        tianfang@linux-k36c:/mnt/share/test>

    这是一个链接错误,它的意思是找不到pthread_create函数的定义。这是因为在Linux上线程函数位于libpthread共享库中,因此在编译时要加上-lpthread选项。

    等待线程结束

    有的时候,我们需要等待线程结束,此时才能继续执行后面的事情。拿前面的例子来说,如果不等待线程结束,则主线程(main函数)会直接往下执行导致程序退出,线程函数都无法得到执行。

    pthread库中等待线程结束的函数是pthread_join,它的声明如下:

        #include <pthread.h>
        int pthread_join(pthread_t thread, void **retval);

    它有两个参数,第一个参数是线程标识符,第二个参数是个出参,用户获取线程函数的返回值。pthread_join在前面的例子中已经有演示,这里就不再介绍了。

    终止线程

    终止线程的方法一般来说有如下几种:

    • 线程函数调用return终止自己
    • 线程调用pthread_exit终止自己
    • 线程可以调用pthread_cancel终止同一进程中的其它线程

    其中,方法1和方法2都是通过结束线程函数来实现主动退出的,它们是比较常用的方法。方法3则是一种强制终止的做法,这个方法一个问题就是导致对象的析构函数可能无法执行,会出现资源泄漏,并不推荐用这种方法。

  • 相关阅读:
    【C语言程序设计】C语言渔夫打鱼晒网问题!
    【C语言】很少人真正了解 和 有什么区别!
    【C语言程序设计】C语言求亲密数!
    新手程序员该如何打造自己的个人品牌!谨记,共勉!
    【C语言程序设计】利用数组解决线性代数中的矩阵转置问题!
    【程序员段子】程序员太苦逼了,苍天啊!请给我一次重新择业的机会吧!
    27. Remove Element
    Leetcode Scratching Recorder
    Activity---弹出右侧窗口
    ViewPageIndicator--仿网易的使用
  • 原文地址:https://www.cnblogs.com/TianFang/p/2873793.html
Copyright © 2020-2023  润新知