C语言多线程编程-线程的基本函数

序言

实验室项目采用多线程实现,然而暂时只涉及到几个基本的线程操作函数,线程和进程的区别、线程的同步和异步机制以及线程通信等暂时都没有涉及,打算在这里做些总结,以备后用。

1 线程操作函数

1.1 线程创建函数

int pthread_create (pthread_t * restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn) (void *), void *restrict arg);

说明:创建一个具有指定参数的线程。

形参:
    tidp       要创建的线程的线程id指针
    attr       创建线程时的线程属性
    start_rtn  返回值是void类型的指针函数
    arg        start_rtn的形参

返回值:若是成功建立线程返回0,否则返回错误的编号

头文件:#include <pthread.h>

由restrict 修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于第一个时,才能对对象进行存取

pthread_t类型定义如下
        typedef unsigned long int pthread_t
打印时要使用%lu或%u方式

1.2 等待线程结束函数

int pthread_join(pthread_t thread, void **retval);

说明:这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回

形参:
    thread     被等待的线程标识符
    retval     一个用户定义的指针,它可以用来存储被等待线程的返回值

返回值:成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

1.3 线程退出函数

void pthread_exit(void *retval);

说明:终止调用它的线程并返回一个指向某个对象的指针

形参:
    retval     函数的返回指针,只要pthread_join中的第二个参数retval不是NULL,这个值将被传递给retval

返回值:无

头文件:#include <pthread.h>

1.4 线程取消函数

int pthread_cancel(pthread_t thread);

说明:取消某个线程的执行

形参:
    thread     要取消线程的标识符ID

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

其他说明:一个线程能够被取消并终止执行需要满足两个条件(1) 线程是否可以被取消,默认可以被取消;(2) 线程处于可取消点才能取消,可以设置线程为立即取消只能在取消点被取消。

1.5 设置可取消状态函数

int pthread_setcancelstate (int state, int *oldstate);

说明:设置当前线程的可取消性状态

形参:
    state     要更新的心状态值
    oldstate  原来存储的状态

state的合法值:
    PTHREAD_CANCEL_DISABLE  针对目标线程的取消请求将处于未决状态,请求未处理但仍然存在,除非该线程修改自己的状态,否则不会被取消
    PTHREAD_CANCEL_ENABLE   针对目标线程的取消请求将被传递,此状态为创建线程时的默认状态

返回值:成功返回0,否则返回错误编号以指明错误

1.6 设置取消类型函数

int pthread_setcanceltype (int type, int *oldtype);

说明:设置当前线程的取消类型,即设置在接收到取消操作后是立即终止还是在取消点终止

形参:
    type     为调用线程新的可取消性
    oldtype  存储原来的类型

type的合法值如下:
    PTHREAD_CANCEL_ASYNCHRONOUS  可随时执行新的或未决的取消请求
    PTHREAD_CANCEL_DEFERRED      目标线程到达一个取消点之前,取消请求将一直处于未决状态;此类型为创建线程时的默认类型

返回值:成功返回0,否则返回错误编号以指明错误

1.7 获取当前线程ID函数

pthread_t pthread_self (void);

说明:获取当前调用线程的 thread identifier(标识号)
形参:无
返回值:当前线程的线程ID标识
头文件:#include <pthread.h>

1.8 分离释放线程函数

int pthread_detach (pthread_t thread);

说明:线程资源释放方式设置函数

形参:
    thread     要释放线程的标识符ID

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>
  • 其他说明:linux线程执行和windows不同,pthread有两种状态joinable状态和unjoinable状态。

    • 一个线程默认的状态是joinable,如果线程是joinable状态,当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符(总计8K多),只有当你调用了pthread_join之后这些资源才会被释放。

    • 若是unjoinable状态的线程,这些资源在线程函数退出时或pthread_exit时自动会被释放。

    • unjoinable属性可以在pthread_create时指定,或在线程创建后在线程中pthread_detach自己设置, 如:pthread_detach(pthread_self()),将状态改为unjoinable状态,确保资源的释放。如果线程状态为joinable,需要在之后适时调用pthread_join。

1.9 比较两个线程是否是同一线程

int pthread_equal (pthread_t thread1, pthread_t thread2);

说明:判断两个线程ID是否是同一个

形参:
    thread1     要比较的线程的标识符ID1
    thread2     要比较的线程的标识符ID2

返回值:不相等返回0,相等非零

头文件:#include <pthread.h>

1.10 线程私有数据操作函数

创建线程私有数据
int pthread_key_create (pthread_key_t *key, void (*destr_function) (void *));

说明:创建线程私有数据TSD,提供线程私有的全局变量。使用同名而不同内存地址的线程私有数据结构

形参:
    key       线程私有数据
    第二个参数  如果第二个参数不为空,在线程退出时将以key所关联数据为参数调用其指向的资源释放函数,以释放分配的缓冲区

其他说明:不论哪个线程调用pthread_key_create()函数,所创建的key都是所有线程可访问的,但各个线程可根据自己的需要往key中填入不同的值
相当于提供了同名不同值的全局变量,各线程对自己私有数据操作互相不影响

注销线程私有数据
int pthread_key_delete (pthread_key_t *key);

该函数并不检查当前是否有线程正是用该TSD,也不会调用清理函数(destr_function)
将TSD释放以供下一次调用pthread_key_create()使用

读写线程私有数据
写 int pthread_setspecific (pthread_key_t key, const void *pointer);
读 void pthread_getspecific (pthread_key_t key);

函数pthread_setspecific()将pointer的值(非内容)与key相关联
函数pthread_getspecific()将与key相关联的数据读出来
所有数据都设置为void *,因此可以指向任何类型的数据

2. 线程属性函数

属性对象是不透明的,而且不能通过赋值直接进行修改。系统提供了一组函数,用于初始化、配置和销毁线程属性。

2.1 初始化一个线程对象的属性

int pthread_attr_init (pthread_attr_t *attr);

说明:pthread_attr_init实现时为属性对象分配了动态内存空间
     Posix线程中的线程属性pthread_attr_t主要包括scope属性、detach属性、堆栈地址、堆栈大小、优先级
形参:
    attr       指向一个线程属性的指针

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.2 销毁一个线程属性对象

int pthread_attr_destroy (pthread_attr_t *attr);

说明:经pthread_attr_destroy去除初始化之后的pthread_attr_t结构被pthread_create函数调用,将会导致其返回错误

形参:
    attr       指向一个线程属性的指针

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.3 获取线程分离状态属性

int pthread_attr_getdetachstate (pthread_attr_t *attr, int *detachstate);

说明:获取线程分离状态属性;pthread_detach()分离释放线程资源函数

形参:
    attr          指向一个线程属性的指针
    detachstate   保存返回的分离状态属性

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.4 修改线程分离状态属性

int pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate);

说明:修改线程分离状态属性;pthread_detach()分离释放线程资源函数

形参:
    attr         指向一个线程属性的指针
    detachstate  有两个取值
PTHREAD_CREATE_JOINABLE(可连接),使用attr创建的所有线程处于可连接状态,线程终止不会回收相关资源,需在其他线程调用pthread_detach()或pthread_join()函数
PTHREAD_CREATE_DETACHED(分离),使用attr创建的所有线程处于分离状态,这类线程终止带有此状态的线程相关资源将被系统收回

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.5 获取线程间的CPU亲缘性

int pthread_attr_getaffinity_np (pthread_attr_t *attr, size_t cpusetsize, cpu_set_t *cpuset);

说明:获取线程的CPU亲缘属性

形参:
    attr         指向一个线程属性的指针
    cpusetsize   指向CPU组的缓冲区大小
    cpuset       指向CPU组的指针

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.6 设置线程的CPU亲缘性

int pthread_attr_setaffinity_np (pthread_attr_t *attr, size_t cpusetsize, const cpu_set_t *cpuset);

说明:通过指定cupset来设置线程的CPU亲缘性

形参:
    attr         指向一个线程属性的指针
    cpusetsize   指向CPU组的缓冲区大小
    cpuset       指向CPU组的指针

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.7 获取线程的作用域

int pthread_attr_getscope (pthread_attr_t *attr, int *scope);

说明:指定了作用域也就指定了线程与谁竞争资源

形参:
    attr       指向一个线程属性的指针
    scope      返回线程的作用域

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.8 设置线程的作用域

int pthread_attr_setscope (pthread_attr_t *attr, int scope);

说明:指定了作用域也就指定了线程与谁竞争资源

形参:
    attr       指向一个线程属性的指针
    scope      线程的作用域,可以取如下值
PTHREAD_SCOPE_SYSTEM  与系统中所有进程中线程竞争
PTHREAD_SCOPE_PROCESS 与当前进程中的其他线程竞争

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.9 获取线程的栈保护区大小

int pthread_attr_getguardsize (pthread_attr_t *attr, size_t *guardsize);

说明:获取线程的栈保护区大小

形参:
    attr       指向一个线程属性的指针
    guardsize  返回获取的栈保护区大小

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.10 设置线程的栈保护区大小

int pthread_attr_setguardsize (pthread_attr_t *attr, size_t *guardsize);

说明:参数提供了对栈指针溢出的保护。默认为系统页大小,如果设置为0表示没有保护区。
     大于0,则会为每个使用 attr 创建的线程提供大小至少为 guardsize 字节的溢出保护区

形参:
    attr       指向一个线程属性的指针
    guardsize  线程的栈保护区大小

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.11 获取线程的堆栈信息(栈地址和栈大小)

int pthread_attr_getstack (pthread_attr_t *attr, void **stackaddr, size_t *stacksize);

说明:获取线程的堆栈地址和大小

形参:
    attr       指向一个线程属性的指针
    stackaddr  返回获取的栈地址
    stacksize  返回获取的栈大小

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.12 设置线程的堆栈区

int pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, size_t stacksize);

说明:设置堆栈区,将导致pthread_attr_setguardsize失效

形参:
    attr       指向一个线程属性的指针
    stackaddr  线程的堆栈地址:应该是可移植的,对齐页边距的,可以用posix_memalign来进行获取
    stacksize  线程的堆栈大小:应该是页大小的整数倍

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.13 获取线程堆栈地址

int pthread_attr_getstackaddr (pthread_attr_t *attr, void **stackaddr);

说明:函数已过时,一般用pthread_attr_getstack来代替

形参:
    attr       指向一个线程属性的指针
    stackaddr  返回获取的栈地址

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.14 设置线程堆栈地址

int pthread_attr_setstackaddr (pthread_attr_t *attr, void *stackaddr);

说明:函数已过时,一般用pthread_attr_setstack来代替

形参:
    attr       指向一个线程属性的指针
    stackaddr  设置线程堆栈地址

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.15 获取线程堆栈大小

int pthread_attr_getstacksize (pthread_attr_t *attr, size_t *stacksize);

说明:获取线程堆栈大小

形参:
    attr       指向一个线程属性的指针
    stacksize  返回线程的堆栈大小

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.16 设置线程堆栈大小

int pthread_attr_setstacksize (pthread_attr_t *attr, size_t stacksize);

说明:设置线程堆栈大小

形参:
    attr       指向一个线程属性的指针
    stacksize  设置线程的堆栈大小,stack属性的合法值包括
    PTHREAD_STACK_MIN 该线程的用户栈大小将使用默认堆栈大小,为某个线程所需最小堆栈大小,但对于所有线程,这个大小可能无法接受
    具体指定的大小       使用线程的用户堆栈大小的数值,必须不小于最小堆栈大小PTHREAD_STACK_MIN

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>

2.17 获取线程的调度策略

int pthread_attr_getschedpolicy (pthread_attr_t *attr, int *policy);

说明:获取线程的调度策略

形参:
    attr       指向一个线程属性的指针
    policy     返回线程的调度策略

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>
        #include <sched.h>

按照如下方法使用sched_get_priority_max ( )和sched_get_priority_min ( ),可以得到优先级的最大值和最小值。
调用形式

#include <sched.h> 
int sched_get_priority_max(int policy);  
int sched_get_priority_min(int policy); 

两个函数都以调度策略policy为参数,目的是获得对应调度策略的优先级值,而且都返回调度策略的最大或最小优先级值。

2.18 设置线程的调度策略

int pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy);

说明:设置线程的调度策略

形参:
    attr       指向一个线程属性的指针
    policy     线程的调度策略,posix指定了3种调度策略属性:
               SCHED_FIFO    先入先出策略
               SCHED_RR      轮转调度,类似于 FIFO,但加上了时间轮片算法
               SCHED_OTHER   系统默认策略

SCHED_OTHER是不支持优先级使用的
SCHED_FIFO和SCHED_RR支持优先级的使用,他们分别为1和99,数值越大优先级越高

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>
        #include <sched.h>

2.19 获取线程的调度参数

int pthread_attr_getschedparam (pthread_attr_t *attr, struct sched_param *param);

说明:获取线程的调度参数

形参:
    attr       指向一个线程属性的指针
    param      返回获取的调度参数

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>
        #include <sched.h>

2.20 设置线程的调度参数

int pthread_attr_setschedparam (pthread_attr_t *attr, const struct sched_param *param);

说明:设置线程的调度参数,用于设置优先级

形参:
    attr       指向一个线程属性的指针
    param      要设置的调度参数,sched_param结构体至少需要定义这个数据成员
               struct sched_param 
               {
                    int sched_priority;     /* Scheduling priority */
               };
    sched_param可能还有其他的数据成员,以及多个用来返回和设置最小优先级、最大优先级、调度器、参数等的函数。
    如果调度策略是SCHED_FIFO或SCHED_RR,那么要求具有值的唯一成员是sched_priority。

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>
        #include <sched.h>

2.21 获取线程是否继承调度属性

int pthread_attr_getinheritsched (pthread_attr_t *attr, int *inheritsched);

说明:获取线程是否继承调度属性

形参:
    attr          指向一个线程属性的指针
    inheritsched  返回继承调度属性的设置

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>
        #include <sched.h>

2.22 设置线程是否继承调度属性

int pthread_attr_setinheritsched (pthread_attr_t *attr, int inheritsched);

说明:设置线程是否继承调度属性

形参:
    attr          指向一个线程属性的指针
    inheritsched  设置线程是否继承调度属性,可能取值如下

    PTHREAD_INHERIT_SCHED  调度属性将继承于正创建的线程。忽略在 pthread_create() 的attr定义中的调度属性设置
    PTHREAD_EXPLICIT_SCHED 调度属性将被设置为pthread_create()的attr中指定的属性值

返回值:若是成功返回0,否则返回错误的编号

头文件:#include <pthread.h>
        #include <sched.h>

Acknowledgements:

http://blog.csdn.net/zsf8701/article/details/7815307

http://blog.csdn.net/zsf8701/article/details/7843837

http://blog.chinaunix.net/uid-23896168-id-2653836.html

2017.04.11
本人博客会根据个人知识升级情况进行补充修改

    原文作者:shuaixio
    原文地址: https://blog.csdn.net/baidu_35692628/article/details/69487525
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞