IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ pthread库 -> 正文阅读

[C++知识库]C++ pthread库

基本函数

创建线程

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

参数说明:
第一个参数表示线程id。
第二个参数表示线程参数。
第三个是线程的入口函数,入口函数的返回值必须为void*,且入口函数必须为static。
第四个参数表示线程入口函数的参数,类型为void*。

终止线程

void pthread_exit(void *value_ptr);

参数说明:
如果该参数value_ptr不为NULL,那么,此线程调用pthread_exit函数终止时,线程退出返回的值为*value_ptr。

注意:

  1. Linux主线程里使用pthread_exit(val)结束时,只会使主线程结束,而由主线程创建的子线程并不会因此结束,他们继续执行。
  2. Linux主线程使用return结束时,那么子线程也就结束了。
  3. 如果线程是joinable,可以在函数参数里面传递线程的退出信息给主线程。

连接线程

int pthread_join(pthread_t tid, void **status);

参数说明
第一个参数表示等待线程的id。
第二个参数表示该线程结束时的返回值。

注意:

  1. 等待终止的线程应该处于joinable(结合)状态,即非DETACHED(分离)状态。
  2. joinable的线程必须用pthread_join()函数来释放线程所占用的资源,如果没有执行这个函数,那么线程的资源永远得不到释放。
  3. 一个线程仅允许唯一的一个线程使用pthread_join()等待它的终止,否则后面调用的pthread_join会返回错误。

分离线程

int pthread_detach(pthread_t thread);

参数说明
想要分离的某个线程的tid;

注意:

  1. 将该线程分离后,此线程结束后,会自动释放其所占资源。
  2. 一般来说,如果没有用pthread_detach分离的线程,都会使用ptread_join来回收其线程所占资源。

互斥量mutex

互斥量的使用流程一般如下所示:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/
pthread_mutex_init(&mutex,NULL);/*动态初始化互斥锁*/
pthread_mutex_lock(&mutex);//加锁
pthread_mutex_unlock(&mutex);//解锁
pthread_mutex_destroy(&mutex);//销毁互斥锁

示例:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

pthread_mutex_t mutex ;
void *print_msg(void *arg){
        int i=0;
        pthread_mutex_lock(&mutex);
        for(i=0;i<15;i++){
                printf("output : %d\n",i);
                usleep(100);
        }
        pthread_mutex_unlock(&mutex);
}
int main(int argc,char** argv){
        pthread_t id1;
        pthread_t id2;
        pthread_mutex_init(&mutex,NULL);
        pthread_create(&id1,NULL,print_msg,NULL);
        pthread_create(&id2,NULL,print_msg,NULL);
        pthread_join(id1,NULL);
        pthread_join(id2,NULL);
        pthread_mutex_destroy(&mutex);
        return 1;
}

条件变量cond

条件变量的使用流程如下:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化条件变量*/
pthread_mutex_lock(&mutex);/*锁住互斥量*/
pthread_cond_signal(&cond);//发送信号量 跟wait函数不在同一个线程中
pthread_cond_wait(&cond,&mutex);//阻塞线程,等待条件变量,同时解锁互斥量
pthread_mutex_unlock(&mutex);//解锁互斥量
pthread_mutex_destroy(&mutex);//销毁互斥锁
pthread_cond_destroy(&cond);//销毁条件变量

示例:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化条件变量*/

void *thread1(void *);
void *thread2(void *);

int i=1;

int main(void)
{
	pthread_t t_a;
	pthread_t t_b;
	pthread_create(&t_a,NULL,thread1,(void *)NULL);/*创建进程t_a*/
	pthread_create(&t_b,NULL,thread2,(void *)NULL); /*创建进程t_b*/
	pthread_join(t_a, NULL);/*等待进程t_a结束*/
	pthread_join(t_b, NULL);/*等待进程t_b结束*/
	pthread_mutex_destroy(&mutex);
	pthread_cond_destroy(&cond);
	exit(0);
}
void *thread1(void *junk)
{
	for(i=1;i<=6;i++)
	{
		printf("thread1: Line: %d, i = %d\n", __LINE__, i);
		pthread_mutex_lock(&mutex);/*锁住互斥量*/
		printf("thread1: lock %d\n", __LINE__);
		if(i%3==0)
		{
			printf("thread1:signal 1 %d\n", __LINE__);
			pthread_cond_signal(&cond);/*条件改变,发送信号,通知t_b进程*/
			printf("thread1:signal 2 %d\n", __LINE__);
			printf("%s will sleep 1s in Line: %d \n", __FUNCTION__, __LINE__);
			sleep(1);
		}
		pthread_mutex_unlock(&mutex);/*解锁互斥量*/
		printf("thread1: unlock %d\n", __LINE__);
		printf("%s will sleep 1s in Line: %d \n\n", __FUNCTION__, __LINE__);
		sleep(1);
	}
}


void *thread2(void *junk)
{
	while(i<6)
	{
		printf("thread2: Line: %d, i = %d\n", __LINE__, i);
		pthread_mutex_lock(&mutex);
		printf("thread2: lock %d\n", __LINE__);
		if(i%3!=0)
		{
			printf("thread2: wait 1 %d\n", __LINE__);
			pthread_cond_wait(&cond,&mutex);/*解锁mutex,并等待cond改变*/
			printf("thread2: wait 2 %d\n", __LINE__);
		}
		pthread_mutex_unlock(&mutex);
		printf("thread2: unlock %d\n", __LINE__);
		printf("%s will sleep 1s in Line: %d \n\n", __FUNCTION__, __LINE__);
		sleep(1);
	}
}

结果为:

thread1: Line: 29, i = 1
thread1: lock 31
thread1: unlock 41
thread1 will sleep 1s in Line: 42 

thread2: Line: 52, i = 1
thread2: lock 54
thread2: wait 1 57
thread1: Line: 29, i = 2
thread1: lock 31
thread1: unlock 41
thread1 will sleep 1s in Line: 42 

thread1: Line: 29, i = 3
thread1: lock 31
thread1:signal 1 34
thread1:signal 2 36
thread1 will sleep 1s in Line: 37 
thread1: unlock 41
thread1 will sleep 1s in Line: 42 

thread2: wait 2 59
thread2: unlock 62
thread2 will sleep 1s in Line: 63 

thread1: Line: 29, i = 4
thread1: lock 31
thread1: unlock 41
thread1 will sleep 1s in Line: 42 

thread2: Line: 52, i = 4
thread2: lock 54
thread2: wait 1 57
thread1: Line: 29, i = 5
thread1: lock 31
thread1: unlock 41
thread1 will sleep 1s in Line: 42 

thread1: Line: 29, i = 6
thread1: lock 31
thread1:signal 1 34
thread1:signal 2 36
thread1 will sleep 1s in Line: 37 
thread1: unlock 41
thread2: wait 2 59
thread2: unlock 62
thread2 will sleep 1s in Line: 63 

thread1 will sleep 1s in Line: 42 

其余函数

//获取本线程的tid(线程id),经常作为pthread_detach的参数
pthread_t pthread_self(void);

//创建线程的私有变量;
//参数一:创建的私有变量;
//参数二:在线程结束退出后,调用该函数清理线程私有变量(即线程存储)
int pthread_key_create(pthread_key_t *key,void(*destructor)(void*));

//设置key(关键字)所关联的私有地址
//参数一:所要设置的关键字
//参数二:key所要代表的那个地址
int pthread_setspecific(pthread_key_t key, const void *value);

//删除键所占的内存;
int pthread_key_delete(pthread_key_t key);

//一次执行函数,用来在多线程中,表示某个方法只会执行一次。(即在一个进程里,参数二所指向的函数只会执行一次)
//参数一:表示一次性初始化,通常用pthread_once_t once_control=PTHREAD_ONCE_INIT来初始化;
//参数二:指向某个函数
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));

//该函数向指定的线程发送信号用来请求结束它,注意:只是请求;该线程也可以不结束
int pthread_cancel(pthread_t thread);

//用来设置本线程对pthread_cancel函数发送信号的反应
//参数一:state有两种状态,PTHREAD_CANCEL_ENABLE(缺省)和PTHREAD_CANCEL_DISABLE分别表示,忽略此信号(也就是用pthraed_cancel不能结束本线程)和信号继续运行(可以结束本线程)
int pthread_setcancelstate(int state, int *oldstate);

//设置用pthread_cancel请求结束线程时,是立即结束还是延迟结束(取消点退出)
//参数一:有两种取值PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS分别表示取消点退出和立即退出。前提:在pthread_setcancelstate设置成ENABLE有效。
//如果不为NULL,用来获取之前的取消类型值。
int pthread_setcanceltype(int type, int *oldtype);

//设置取消点。当然,除了pthread_testcancel设置的取消点外还有其他默认的取消点;
void pthread_testcancel(void);

//这两个函数要在同一个临界区里(即{}),不能分开。
//这组函数叫线程清理函数,当线程结束时会调用线程清理函数routine所指向的函数。
//当函数 pthread_cleanup_pop(1)参数非0时,当本线程调用pthread_exit()或者其他线程调用pthread_cancel()或者执行到pthread_cleanup_pop函数时,会调用清理函数。
//当函数 pthread_cleanup_pop(0)参数为0时,当本线程调用pthread_exit()或者其他线程调用pthread_cancel(),会调用清理函数。
void pthread_cleanup_push(void (*routine)(void *), void *arg);
void pthread_cleanup_pop(int execute);

线程属性

线程属性结构体

typedef struct {
      int    threadAttrStatus;  /* status flag              */
      size_t threadAttrStacksize;  /* stack size               */
      void * threadAttrStackaddr;  /* stack address            */
      size_t threadAttrGuardsize;  /* guard address (RTP only)线程栈末尾的警戒缓冲区大小 */
      int    threadAttrDetachstate;  /* detach state   分离状态          */
      int    threadAttrContentionscope;  /* contention scope   表线程竞争CPU范围   */
      int    threadAttrInheritsched;  /* inherit scheduler    继承性    */
      int    threadAttrSchedpolicy;  /* scheduling policy   调度策略     */
      struct _Sched_param threadAttrSchedparam; /* sched param struct  调度参数*/
    } pthread_attr_t;


struct _Sched_param  {
    int  sched_priority; /* scheduling priority 表示线程的优先级 */
    }

线程属性函数

//函数说明:
//线程属性的初始化
//参数说明:
//线程属性结构体指针,表示要设置的线程属性
int pthread_attr_init(pthread_attr_t *attr);

//函数说明:
//销毁线程属性,使它恢复为pthread_attr_init调用之前的状态
//参数说明:
//线程属性结构体指针,表示要设置的线程属性
int pthread_attr_destroy(pthread_attr_t *attr);

//函数说明:
//设置线程属性栈的大小
//参数说明: 
//参数一:线程属性结构体指针,表示要设置的线程属性;
//参数二:设置大小的值
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

//函数说明:
//用来获取指定线程属性所设置的栈的大小
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);

//函数说明:
//设置线程属性栈的地址
//参数说明:
//参数一:线程属性结构体指针,表示要设置的线程属性
//参数二:所设置的地址(即stackaddr指向的地址)
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);

//函数说明:
//用来获取指定线程属性所设置的栈地址
int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr);

//函数说明:
//设置线程属性的分离状态:分离线程在该线程结束退出后会自动清理所占资源;非分离线程则需要调用pthread_join来回收资源。
//参数说明:
//参数一:线程属性结构体指针,表示要设置的线程属性
//参数二:有两个值PTHREAD_CREATE_DETACHED(分离线程)、PTHREAD_CREATE_JOINABLE(非分离线程)
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

//函数说明:
//获取线程属性的分离状态
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);

//函数说明:
//设置线程竞争CPU的范围
//参数说明:
//参数一:线程属性结构体指针,表示要设置的线程属性
//参数二:有两个值PTHREAD_SCOPE_SYSTEM和PTHREAD_SCOPE_PROCESS,前者表示与系统中所有线程一起竞争CPU时间,后者表示仅与同进程中的线程竞争CPU。默认为PTHREAD_SCOPE_PROCESS。
int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);

//函数说明:
//获取指定线程属性的线程竞争范围情况
int pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope);

//函数说明:
//用来设置线程的继承性。要么是从创建它的线程里继承调度属性(调度策略、调度参数),要么是从线程属性里通过pthread_attr_setschedpolicy和pthread_attr_setschedparam里获得调度属性。
//参数说明:
//参数一:线程属性结构体指针,表示要设置的线程属性
//参数二:有两个值选择,PTHREAD_INHERIT_SCHED: 新的线程调度策略和参数继承于创建它的线程;PTHREAD_EXPLICIT_SCHED:新的线程继承策略和参数来自于schedpolicy和schedparam属性中显式设置的调度信息。
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);

//函数说明:
//获取线程属性继承性
//注:继承性决定调度的参数是从创建它的进程中继承还是使用在 schedpolicy和schedparam属性中显式设置的调度信息。
int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched);

//函数说明:
//设置线程调用策略
//参数说明:
//参数一:线程属性变量
//参数二:设置的策略,有三个值选择:
//SCHED_FIFO :先进先出
//SCHED_RR   :轮转法
//SCHED_OTHER:其他方法
//SCHED_OTHER是不支持优先级使用的,而SCHED_FIFO和SCHED_RR支持优先级的使用,他们分别为1和99,数值越大优先级越高.
/*注意:
   > 此处的SCHED_FIFO是允许被高优先级抢占的!
   > 也就是有高优先级的必须先运行
   > SCHED_RR是设置一个时间片
   > 当有SCHED_FIFO或SCHED_RR策赂的线程在一个条件变量上等持或等持加锁同一个互斥量时,它们将以优先级顺序被唤醒。即,如果一个低优先级的SCHED_FIFO线程和一个高优先级的SCHED_FIFO线程都在等待锁相同的互斥且,则当互斥量被解锁时,高优先级线程将总是被首先解除阻塞。*/
//当然SCHED_RR和SCHED_FIFO还是有区别的,后者是先进先出,必须是一个线程运行完了后才执行下一个线程。而SCHED_RR是在线程运行完设置的时间片后切换,虽然它是先运行优先级高的线程,但是它先将此次运行过的线程放在线程队列的后面,再从前向后寻找优先级高的线程,进行执行。
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);

//函数说明:
//获取线程的调度策略
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);

//函数说明:
//设置线程的调度参数
//参数说明:
//参数一:线程属性变量
//参数二:sched_parm 结构体
int pthread_attr_setschedparam(pthread_attr_t *attr,const struct sched_param *param);

//函数说明
//获取线程属性的调度参数
int pthread_attr_getschedparam(const pthread_attr_t *attr,struct sched_param *param);

//函数说明:
//系统支持的最大和最小的优先级值可以用函数
//注意参数是policy调用策略,也就是说对于不同的策略的值是不一样的
int sched_get_priority_max( int policy );
int sched_get_priority_min( int policy );




  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-24 00:01:57  更:2021-07-24 00:02:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/8 9:34:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码