• 线程


    在linux平台上,在编译调用了PthreadsAPI的程序时,需要设置 cc -pthread(等价于-lpthread)的编译选项

    #include<pthread.h>
    int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start)(void *),void *arg);  //创建一条新线程
    
    void pthread_exit(void *retval);    //终止调用线程,且其返回值可由另一线程通过调用pthread_join()来获取
    
    pthread_t pthread_self(void);   //线程id会返回给pthread_create()的调用者,一个线程可以通过pthread_self()来获取自己的线程id
    
    int pthread_equal(pthread_t t1,pthread_t t2)    //检查两个进程的id是否相同,如果相等返回非0
    
    int pthread_join(pthread_t thread,void **retval);   //等待有thread标识的线程终止,如果已经终止,立即返回,这种操作称为连接,retval将会保存线程终止时返回值的拷贝,即return或pthread_exit()指定的值
    
    //向thread参数传入指定线程的标识符,并将该线程记为处于分离状态,一旦线程处于分离状态,就不能使用pthread_join来获取其状态
    int pthread_detach(pthread_t thread);   
    如有任一线程调用了exit(),那么所有线程立即终止
    

    线程同步
    互斥量是属于pthread_mutex_t类型的变量,在使用之前必须对其初始化
    pthread_mutex_t mtx=PTHEAD_MUTEX_INITIALIZER; //静态初始化,保护位于锁定互斥量内的变量

    int pthread_mutex_lock(pthread_mutex_t *mutex);     //锁定互斥量
    int pthread_mutex_unlock(pthread_mutex_t,*mutex);   //解锁互斥量
    
    //动态初始化互斥量,参数mutex指定函数执行初始化操作的目标互斥量
    int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);
    //摧毁动态分配的互斥量,静态初始化的互斥量则不需要
    int pthread_mutex_destroy(pthread_mutex_t *mutex);  
    
    //互斥量类型
    PTHREAD_MUTEX_NORMAL    //不具有死锁检测(自检)功能
    PTHREAD_MUTEX_ERRORCHECK    //对此类互斥量的所有操作都会执行错误检查
    PTHREAD_MUTEX_PECURSIVE     //递归互斥量维护有一个锁计数器,当锁计数器值降为0时,释放该互斥量
    
    //条件变量的数据类型是pthread_cond_t ,下面是静态初始化
    pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
    
    int pthread_cond_signal(pthread_cond_t *cond);  //针对cond所指定的条件变量发送信号(唤醒至少一条遭到阻塞的线程)
    int pthread_cond_broadcast(pthread_cond_t *cond); //针对cond所指定的条件变量发送信号(唤醒所有遭到阻塞的线程)
    int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex); //阻塞一线程,直到收到条件变量cond的通知,必须由一个while循环而不是if语句来控制对pthread_cond_wait()的调用
    
    //abstime指定一个线程等待条件变量通知时休眠时间的上限
    int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex,const struct timespec *abstime); 
    
    //动态分配条件变量
    int pthread_cond_init(pthead_cond_t *cond,const pthread_condattr_t *attr);
    //摧毁动态条件变量
    int pthread_cond_destroy(pthread_cond_t *cond);
    

    线程安全和每线程存储

    //实现一次性初始化
    //利用once_control的状态,可以确保无论有多少线程对pthread_once调用多少次,也只会执行一次由init指向的调用者定义函数
    int pthread_once(pthread_once_t *once_control,void(*init)(void));
    //once_control必须是指针,指向初始化为PTHREAD_ONCE_INIT的静态变量
    pthread_once_t once_var=PTHREAD_ONCE_INIT;
    
    //为线程特有数据创建一个新键,并通过key所指向的缓冲区返回给调用者
    //返回的pthread_key_t类型值只是对全局数组的索引,标记为pthread_keys
    //数组的每个元素都包含两个字段,第一个字段标记该数组元素是否在用,第二个用于存放针对此键,线程特有数据块的解构函数指针
    int pthread_key_create(pthread_key_t *key,void (*destructor)(void *));
    
    //将value的副本存储与一数据结构中,并将value与调用线程以及key相关联
    int pthread_setspecific(pthread_key_t key,const void *value);
    //跟上面的函数相反,返回之前与本线程及给定key的值
    void *pthread_getspecific(pthread_key_t key);
    
    //创建线程局部变量,只需要在全局或静态变量的声明中包含_thread说明符即可
    //但凡带有这种说明符,每个进程都拥有一份对变量的拷贝,线程局部存储中的变量将一直存在,直到线程终止,届时自动释放这一存储
    static _thread buf[MAX_ERROR_LEN];

    线程的取消

    //向由thread指定的线程发送一个取消请求
    int pthread_cancel(pthread_t thread);
    
    //调用线程的取消性状态设置为state所给定的值
    int pthread_setcancelstate(int state,int *oldstate);
    //state的值如下
    PTHREAD_CANCEL_DISABLE      //线程不可取消,如果收到取消请求,则会将请求挂起,直至线程的取消状态置为启用
    PTHREAD_CANCEL_ENABLE       //线程可以取消,这是新建线程取消性状态的默认值
    PTHREAD_CANCEL_ASYNCHRONOUS //可能会在任何时点取消线程
    PTHREAD_CANCEL_DEFERED      //取消请求保持挂起状态,直至到达取消点,这也是新建线程的缺省类型
    int pthread_setcanceltype(int type,int *oldtype);
    
    //产生一个取消点,线程如果已有处于挂起状态的取消请求,那么只要调用该函数,线程就会随之终止
    void pthread_testcancel(void);
    
    //每个线程都可以拥有一个清理函数栈,当线程遭取消时,会沿该栈自顶向下一次执行清理函数,首先会执行最近设置的函数,接着是次新的,以此类推,当执行完所有清理函数后,线程终止
    //增加清理函数
    void pthread_clearnup_push(void (*routine)(void *),void *arg);
    //移除清理函数,如果execute非0,无论如何都会执行清理函数
    void pthread_cleanup_pop(int execute);
    
    #include<signal.h>
    //获取或/并改变当前的信号掩码,除了所操作的是线程信号掩码外,该函数与sigprocmask()的用法完全相同
    int pthread_sigmask(int how,const sigset_t *set,sigset_t *oldset);
    
    //向同一进程下的另一线程发送信号sig,目标线程有thread标识,因为仅在同一进程中可保证线程id的唯一性,所以无法调用pthead_kill()向其他进程中的线程发送信号
    int pthread_kill(pthread_t thread,int sig);
    
    //向统一进程中的另一线程发送携带数据的信号
    int pthread_sigqueue(pthread_t thread,int sig,const union sigval value);
    
    //等待set所指信号集合中的任一信号的到达,接收该信号,且在sig中将其返回,返回信号编号
    int sigwait(const sigset_t *set,int *sig);
  • 相关阅读:
    车标知识学习网页开发,与Flask通过base64展示二进制图片 #华为云·寻找黑马程序员#
    大型情感剧集Selenium:3_元素定位 #华为云·寻找黑马程序员#
    大型情感剧集Selenium:2_options设置 #华为云·寻找黑马程序员#
    【nodejs原理&源码赏析(9)】用node-ssh实现轻量级自动化部署
    大型情感剧集Selenium:1_介绍 #华为云·寻找黑马程序员#
    使用Python开发小说下载器,不再为下载小说而发愁 #华为云·寻找黑马程序员#
    #华为云·寻找黑马程序员#【代码重构之路】如何“消除”if/else
    #华为云·寻找黑马程序员#【代码重构之路】如何优雅的关闭外部资源
    走近深度学习,认识MoXing:初识华为云ModelArts的王牌利器 — MoXing
    开启 J2EE(一)—‘全明星队伍’
  • 原文地址:https://www.cnblogs.com/biaopei/p/7730607.html
Copyright © 2020-2023  润新知