Linux笔记(24)-线程基础

  1. 线程基本知识
1. 创建线程后,地址空间不会发生改变
2. 同时该创建线程的进程退化称为主线程
3. 创建出的子线程和主线程公用地址空间
4. 主线程和子线程有各自独立的pcb
    子线程pcb从主线程拷贝而来
5. 同一进程下的多个线程之间共享除栈数据外的其他用户区数据。
    栈区会平均划分。线程之间可以通过全局变量和堆通信
6. 在Linux下,线程称为轻量级进程。对于内核而言,认为一个pcb就是一个进程。
  1. 线程号和线程ID
1. 线程号和线程ID是有区别的 -- 线程号由内核识别,用户识别线程ID
2. 查看线程id
    a. 找到该线程的进程pid
    b. 使用命令ps -Lf <进程pid号>
    c. LWP为线程id
  1. 多进程与多线程
1. 一个单独的线程可以看作一个进程
2. 多进程:
    始终共享:代码;文件描述符;内存映射区
3. 多线程:
    始终共享:堆;全局变量
4. 线程节约资源
  1. 创建线程
1. 函数原型:<pthread.h>
    int pthread_create(pthread_t *thread,
                    const pthread_attr_t *arr,
                    void *(*start_routine)(void *),
                    void *arg
                    );
2. 参数:
    thread:线程ID -- 一个无符号长整型数
    arr:线程属性 -- 如果子线程设置了分离属性,子线程可以自己释放自己。没有要求可以为NULL。
    start_routine:函数指针 -- 创建出的线程所需要执行的操作的函数
    arg:回调函数的参数 -- 即创建出的线程执行函数时,会将参数传给内部
3. 返回值
    0:创建正确
    >0:错误号。通过错误号来查看错误信息 -- 调用函数char *strerror(int errnum)来查看信息
4. 例如:
    //线程回调函数
    //返回类型为void *,参数类型为void *
    void *myfun(void *arg)
    {
        printf("child thread id = %ld\n", pthread_self());
        return NULL;
    }
    
    pthread_t pthid;
    pthread_create(&pthid, NULL, myfun, NULL);
    printf("parent thread id = %ld\n", pthread_self());
    sleep(1);//当主线程结束后会强制结束子线程,因此等待子线程输出
5. arg参数传递应该注意传递址还是传值
    避免由于传地址时,cpu被抢占,使得原来的地址发生变化
6. 命令行编译
    gcc xxpthread_create.c -lpthread
  1. 线程退出函数:如果想让某线程退出而不影响其他线程,则需要使用函数
1. 函数原型:
    <退出单一线程>
    void pthread_exit(void *retval);
2. 参数:
    retval:线程退出过程中可以携带信息,该指针指向信息的内存块地址
            要么指向全局的内存地址,或者堆的内存地址
  1. 回收子线程函数
1. 函数原型:
    <阻塞等待>
    int pthread_join(pthread_t thread, void **retval);
2. 参数
    thread:要回收的子线程的线程ID
    retval:传出参数 -- 使用方法:void *ptr; pthread_join(thread, &ptr);
            ptr指向一块包含信息的地址
3. 由主线程调用该函数
  1. 线程分离
1. 函数原型:
    int pthread_detach(pthread_t thread);
2. 参数:
    thread:子线程ID
3. 注意:
    a. 调用该函数后,子线程会自动回收自己的pcb
    b. 调用了该函数后,不再需要使用pthread_join
    c. 一般使用pthread_create中设置属性的方式来分离子线程
  1. 杀死(取消)线程
1. 函数原型:
    int pthread_cancel(pthread_t thread);
2. 参数:
    thread:需要杀死的线程ID
3. 注意:
    如果要实现杀死线程ID指定线程,必须在该线程内部实现具有系统调用的函数。
    例如:
        void *myfunc(void *arg)
        {
            while(1)
            {
                int i;
                i = 10;
            }
            return NULL;
        }
        该子线程的回调函数没有系统调用的点,因此pthread_cancel并不会杀死该线程。
4. 设置取消点
    pthread_testcancel();
    该函数无其他作用,只是设置一个系统调用的点,用于杀死线程。
  1. 判断线程ID是否相等(预留函数) – pthread_equal
  2. 设置线程分离属性
1. 线程属性类型:
    pthread_arrt_t arr;
2. 对线程属性初始化
    int pthread_attr_init(pthread_attr_t *attr);
3. 设置线程分离属性:
    a. 函数原型:
        int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
    b. 参数:
        attr:属性类型变量的地址
        detachstate:PTHREAD_CREATE_DETACHED(分离)
                     PTHREAD_CREATE_JOINABLE(不分离)
4. 使用属性设置后,最后需要释放属性变量的空间
    int pthread_attr_destroy(pthread_attr_t *attr);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值