linux c语言高级编程-线程基础

线程基础知识:

程序:二进制文件,存放在磁盘上面的文件
进程:正在运行的程序,它处在内存中,一个进程可以被加载无数次
线程:进程的最小活动单元,一个进程中可以有多个线程,至少有一个线程那就是main函数本身

线程的作用:让代码并行运行,而不被阻塞。例如:播放器,播放音乐必定开启了一个线程,理论上播放歌曲时进程会被卡主,即此时UI界面上面的按钮无法点动,整个程序表现为卡死状态,但是实际上播放歌曲时,可以随意点击按钮或者执行其他的操作,这就是多线程导致。

线程的生命周期

就绪:线程即将要运行。可能是刚创建,也可能是刚从阻塞状态唤醒。
运行:线程正在被执行。单处理器中,同一时刻只有一个线程正在运行,多处理器中,同时运行多个线程。
阻塞:线程无法被执行。比如IO阻塞,条件变量阻塞,互斥锁等。
终止:线程函数执行完毕。可能是自然死亡(运行结束return返回),自杀(调用return提前结束,或者调用pthread_exit结束),也可能是他杀(在其他线程调用pthread_cancel结束,或者被kill掉,随进程结束而结束)导致。

线程相关函数

线程创建:pthread_create
获取线程ID:pthread_self
结束线程:pthread_exit, pthread_cancel
等待线程结束:pthread_join

(1)线程创建:
#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 线程函数
   arg 线程函数的参数
   
   返回值:
   0 成功
   非0 失败

(2)获取线程ID:
#include <pthread.h>

   pthread_t pthread_self(void);
   返回值:线程ID

(3)结束线程:
#include <pthread.h>

   void pthread_exit(void *retval);
   参数:
   retval 线程结束之后的返回值
   返回值:
   无

   int pthread_cancel(pthread_t thread);
   参数:
   thread 线程ID
   返回值:
   0 成功
   非0 失败

(4)等待线程结束:
#include <pthread.h>

   int pthread_join(pthread_t thread, void **retval);
   参数:
   thread 线程ID
   retval 线程返回值或状态

线程属性

线程创建时,默认优先级为0,最大为50

   pthread_attr_t属性的类型
   typedef struct
    {
        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;

线程属性相关函数:
初始化:pthread_attr_init
销毁:pthread_attr_destroy
设置优先级:pthread_attr_setschedparam
获取优先级:pthread_attr_getschedparam

优先级结构体如下:

struct sched_param{   
   int __sched_priority; //所要设定的线程优先级
};

(1)初始化:
#include <pthread.h>

   int pthread_attr_init(pthread_attr_t *attr);
   参数:
   attr 线程属性
   
   返回值:
   0 成功
   非0 失败

(2)销毁:
#include <pthread.h>

   int pthread_attr_destroy(pthread_attr_t *attr);
   参数:
   attr 线程属性
   
   返回值:
   0 成功
   非0 失败

(3)设置优先级:
#include <pthread.h>

   int pthread_attr_setschedparam(pthread_attr_t *attr,  const struct sched_param *param);
   参数:
   attr 线程属性
   param 线程优先级

   返回值:
   0 成功
   非0 失败
   
   pthread_setschedparam(pthread_t thread, int policy,
                         const struct sched_param *param);
    参数:
    thread 线程ID
    policy 线程调度策略(SCHED_RR,SCHED_FIFO,SCHED_OTHER )
    param 调度优先级
      struct sched_param {
           int sched_priority;     /* Scheduling priority */
       };
    成功:返回0
    非0:失败

(4)获取优先级:
#include <pthread.h>

   int pthread_attr_getschedparam(pthread_attr_t *attr,  struct sched_param *param);
   参数:
   attr 线程属性
   param 线程优先级

   返回值:
   0 成功
   非0 失败

	pthread_getschedparam(pthread_t thread, int *policy,
                         struct sched_param *param);
    参数:
    thread 线程ID
    policy 线程调度策略(SCHED_RR,SCHED_FIFO,SCHED_OTHER )
    param 调度优先级
      struct sched_param {
           int sched_priority;     /* Scheduling priority */
       };
    成功:返回0
    非0:失败

实例一(线程创建实例):

	传整型
    void *run(void* arg){
        int a=*((int*)arg);
        while(1){
           printf("------- pthread %d\n",a);
           sleep(1);
        }
    }
    
    int main(int argc,char **argv){
        //pthread_t id[5];
        int i;
        for(i=0;i<5;i++){
           pthread_t id;
           pthread_create(&id,NULL,run,&i); //非阻塞
           usleep(200);
       }
        int b;
        scanf("%d",&b);
    }
    
    传数组
    void *run(void* arg){
        //int *p=(int*)malloc(4*7);
        int p[7];
        memcpy(p,arg,4*7);
        int i=0;
        while(1){
           printf("------- pthread %d\n",p[i++%7]);
           sleep(1);
        }
        //free(p);
    }
    int main(int argc,char **argv){
    
        int a[]={1,2,3,4,5,6,7};
        int i;
        //for(i=0;i<5;i++){
           pthread_t id;
           pthread_create(&id,NULL,run,a); //非阻塞
           usleep(200);
       //}
       //这里需要调用pthread_join函数释放线程资源,创建几个线程 就调用几次
        int b;
        scanf("%d",&b);
    }
    //原则,尽快的将arg指向的内存数据拷到线程函数,以免在主函数中将arg指向的值改变。

实例二(线程优先级):

void *run(void* arg){
	printf("%d\n", *(int*)arg);
}

int main(int argc,char **argv){
    int i;
    pthread_t id[5];
    pthread_attr_t attr;
    pthread_attr_init (&attr);
    struct sched_param par={50};
    pthread_attr_setschedparam(&attr,&par);
    for(i=0;i<5;i++){
       if (i==2) pthread_create(&id[i],NULL,run,&i); //创建线程,默认优先级
       else  pthread_create(&id[i],&attr,run,&i); //创建线程,同时设优先级
       usleep(200000);
    }
    pthread_attr_destroy(&attr);
    //这里需要调用pthread_join函数释放线程资源,创建几个线程 就调用几次
    int b;
    scanf("%d",&b);
}

实例二.1(线程优先级):

void *_ao_test_play_thread(void* arg){
	struct sched_param param;
	int policy=-1;
	struct sched_param s_parm;
    s_parm.sched_priority = sched_get_priority_max(SCHED_FIFO);
	
    printf("schedu max %d min %d, current pri=%d\n",sched_get_priority_max(SCHED_FIFO),sched_get_priority_min(SCHED_FIFO), s_parm.sched_priority);
	
	pthread_getschedparam(pthread_self(),&policy,&param);
  	printf("-------------- policy = %d, param=%d\n", policy, param.sched_priority );
    
	if (0 == pthread_setschedparam(pthread_self(), SCHED_FIFO, &s_parm)) {   
    	printf("IO Thread #%d using high-priority scheduler!", pthread_self());
    }
	pthread_getschedparam(pthread_self(),&policy,&param);
  	printf("-------------- policy = %d, param=%d\n", policy, param.sched_priority );
	while(1) {
		sleep(1);
	}
}

int main(int argc,char **argv){
	pthread_t dmic_thread_id;
    ret = pthread_create(&dmic_play_thread_id, NULL, _ao_test_play_thread, NULL);
	if (ret != 0) {
		IMP_LOG_ERR(TAG, "[ERROR] %s: pthread_create Audio Record failed\n", __func__);
		return -1;
	}
}
注意:线程默认创建调度策略为SCHED_OTHER(为一般线程,priority为0),改变线程调度策略为SCHED_FIFO或者SCHED_RR(实时线程)之后,线程会比一般线程调度优先级要高,实际测试发现,高负载情况下,实时线程运行要比一般线程更容易运行(这符合实时线程优先级高于一般线程的原理)

线程调度也可参考下面的链接:
https://www.cnblogs.com/xiaotlili/p/3510224.html
https://www.cnblogs.com/zhaoyl/archive/2012/09/04/2671156.html
https://blog.csdn.net/caoyan_12727/article/details/52346729
https://blog.csdn.net/weixin_34199405/article/details/88019539

实例三(线程分离属性):

#include <stdio.h>
#include <error.h>
#include <stdlib.h>
#include <pthread.h>
void* thread_run(void* _val)
{
	pthread_detach(pthread_self());  //线程分离之后,不需要调用pthread_join等待线程结束
	printf("%s\n", (char*)_val);
	return NULL;
}
 
 
int main()
{
	pthread_t tid;
	int tret = pthread_create(&tid, NULL, thread_run, "thread_run~~~~~");
	//pthread_join
	//线程分离之后,不需要调用pthread_join等待线程结束
	int b;
    scanf("%d",&b);
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行走在软件开发路上的人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值