zoukankan      html  css  js  c++  java
  • 线程

    在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);
  • 相关阅读:
    poj 3068 Bridge Across Islands
    XidianOJ 1086 Flappy v8
    XidianOJ 1036 分配宝藏
    XidianOJ 1090 爬树的V8
    XidianOJ 1088 AK后的V8
    XidianOJ 1062 Black King Bar
    XidianOJ 1091 看Dota视频的V8
    XidianOJ 1098 突击数论前的xry111
    XidianOJ 1019 自然数的秘密
    XidianOJ 1109 Too Naive
  • 原文地址:https://www.cnblogs.com/biaopei/p/7730607.html
Copyright © 2011-2022 走看看