linux多线程基础(一)

 
线程创建
#include <pthread.h>
int pthread_create(pthread_t *thread,
                     const pthread_attr_t * attr,
                     void *(*start_routine)(void *), void *arg);
参数:
Ø         Thread为创建的线程 ID
Ø         Attr为 创建线程时设置的线程属性(见下文)
Ø         start_routine 为创建的线程所执行的函数。该函数可以返回 void* 类型的返回值,由 pthread_join() 获取。
Ø         arg 为创建的线程所执行的函数的参数。可以为任意类型的参数,传入时转换为 void* 既可, eg: (void*)arg static_cast<void *>(arg);
该函数成功返回零,不成功返回一个 error code,常见错误如下
EAGAIN
system did not have the resources to create the thread, or would exceed system limit on total number of threads in a process
EINVAL
attr parameter is invalid
EPERM
caller does not have the appropriate permissions to set scheduling policy or parameters specified by attr
线程属性
pthread_create()中的 attr参数是一个结构指针,结构中的元素分别对应着新线程的运行属性。如果创建线程时使用该参数,则必须先初始化该参数 pthread_attr_init(&attr);
然后再设置参数中各元素。该结构中定义在 /usr/include/bits/ pthreadtypes.h中 :
/* Attributes for threads. */
typedef struct __pthread_attr_s
{
 int       __detachstate;
 int       __schedpolicy;
 struct    __sched_param __schedparam;
 int       __inheritsched;
 int        __scope;
 size_t    __guardsize;
 int        __stackaddr_set;
 void      *__stackaddr;
 size_t    __stacksize;
} pthread_attr_t;
其中各元素含义:
Ø         __detachstate,表示新线程是否与进程中其他线程脱离同步,如果置位则新线程不能用pthread_join()来同步,且在退出时自行释放所占用的资源。缺省为PTHREAD_CREATE_JOINABLE状态。这个属性也可以在线程创建并运行以后用pthread_detach()来设置,而一旦设置为PTHREAD_CREATE_DETACH状态(不论是创建时设置还是运行时设置)则不能再恢复到PTHREAD_CREATE_JOINABLE状态。该参数涉及函数:
 int pthread_attr_setdetachstate (pthread_attr_t *__attr,
int __detachstate);
int pthread_attr_getdetachstate (__const pthread_attr_t *__attr,
                    int *__detachstate);
        __detachstate可取值: PTHREAD_CREATE_JOINABLE, PTHREAD_CREATE_DETACH。
Ø         __schedpolicy,表示新线程的调度策略,主要包括 SCHED_OTHER(正常、非实时)、SCHED_RR(实时、轮转法)和SCHED_FIFO(实时、先入先出)三种,缺省为SCHED_OTHER,后两种调度策略仅对超级用户有效。运行时可以用过pthread_setschedparam()来改变。该参数涉及函数:
int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy);
int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict
                                __attr, int *__restrict __policy);
Ø         __schedparam,一个 struct sched_param结构,其中有一个sched_priority整型变量表示线程的运行优先级。这个参数仅当调度策略为实时(即SCHED_RR或SCHED_FIFO)时才有效,并可以在运行时通过pthread_setschedparam()函数来改变,缺省为0。该参数涉及函数:
nt pthread_attr_setschedparam (pthread_attr_t *__restrict __attr,
                                __const struct sched_param *__restrict  __param);
int pthread_attr_getschedparam (__const pthread_attr_t *__restrict  __attr,
                                struct sched_param *__restrict __param);
Ø         __inheritsched,有两种值可供选择: PTHREAD_EXPLICIT_SCHED和PTHREAD_INHERIT_SCHED,前者表示新线程使用显式指定调度策略和调度参数(即attr中的值),而后者表示继承调用者线程的值。缺省为PTHREAD_EXPLICIT_SCHED。
int pthread_attr_setinheritsched (pthread_attr_t *__attr,
                     int __inherit);
int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict
                     __attr, int *__restrict __inherit);
Ø         __scope,表示线程间竞争 CPU的范围,也就是说线程优先级的有效范围。POSIX的标准中定义了两个值:PTHREAD_SCOPE_SYSTEM和PTHREAD_SCOPE_PROCESS,前者表示与系统中所有线程一起竞争CPU时间,后者表示仅与同进程中的线程竞争CPU。该参数涉及函数:
int pthread_attr_setscope (pthread_attr_t *__attr, int __scope);
int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr,
                             int *__restrict __scope);
pthread_attr_t结构中还有一些值,但不使用 pthread_create()来设置。
另外还有 pthread_attr_destroy(pthread_attr_t *attr),该函数使线程属性无效。
 
线程取消
线程取消一般分为两种情况,一种是线程主体函数退出时自动取消或者调用pthread_exit()退出,另一种是接收到终止请求而退出。
    当线程接收到 cancel信号时,有不同的处理方法,或者忽略、或者立即终止、或者继续运行至 Cancelation-point(取消点),由不同的Cancelation状态决定。缺省处理是执行到取消点退出。
    取消点 : pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会引起阻塞的系统调用都是取消点(Cancelation-point)。由于C库函数都不是取消点,所以可以在需要作为取消点的系统调用前后均调用pthread_testcancel。
    涉及的几个函数:
Ø         int pthread_cancel(pthread_t thread)
发送终止信号给 thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止。
Ø         int pthread_setcancelstate(int state, int *oldstate)
设置本线程对 Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为NULL则存入原来的Cancel状态以便恢复。
Ø         int pthread_setcanceltype(int type, int *oldtype)
设置本线程取消动作的执行时机, type由两种取值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。
Ø         void pthread_testcancel(void)
检查本线程是否处于 Canceld状态,如果是,则进行取消动作,否则直接返回。
 
当线程属性__detachstate设置为PTHREAD_CREATE_JOINABLE时,可以在主线程调用pthread_join()来进行等待(同步)。
函数原型:
    int pthread_join (pthread_t __th, void **__thread_return);
__th为需要等待的线程 ID,第二个参数为该线程的返回值。需要注意的是一个线程仅允许唯一的一个线程使用 pthread_join()等待它的终止,并且被等待的线程应该处于可join状态,即非DETACHED状态。如果进程中的某个线程执行了pthread_detach(th),则th线程将处于DETACHED状态,这使得th线程在结束运行时自行释放所占用的内存资源,同时也无法由pthread_join()同步,pthread_detach()执行之后,对th请求pthread_join()将返回错误。
一个可 join的线程所占用的内存仅当有线程对其执行了pthread_join()后才会释放,因此为了避免内存泄漏,所有线程的终止,要么已设为DETACHED,要么就需要使用pthread_join()来回收。
    建议在函数结束时调用 pthread_exit(),不采用return 。
 
 
 
线程私有数据
    多线程中,由于数据空间共享,所以全局数据和静态数据也是共享的,如果各线程中需要自己线程内的“全局变量”则需要用到线程私有数据 (Thread-specific Data,或 TSD)。线程私有数据采用同名而不同地址的方法实现。一般是函数内存放在堆栈中的数据。
涉及相关函数:
Ø         int pthread_key_create (pthread_key_t *__key,
                   void (*__destr_function) (void *));
    该函数创建一个私有数据 key。其中第二个参数为清理函数,即该key释放时调用该函数用来清理。
Ø         int pthread_key_delete (pthread_key_t __key);
该函数用来释放创建的 key
Ø         int pthread_setspecific (pthread_key_t __key,
                __const void *__pointer);
    该函数用来将 __printer的值与__key相连。
Ø         void *pthread_getspecific (pthread_key_t __key);
该函数用来读取和 __key相关联的数据。
一般使用情况:
全局变量中声明 pthread_key_t __key,主线程中创建该key,然后该key分别与各线程中的私有数据关联,一般是指函数内存放在堆栈中的数据。其他函数调用pthread_getspecific函数可取得该key关联的数据,以实现全局变量的功能。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值