【嵌入式】Linux C编程——多线程编程总结

1、线程的基本概念:

  • 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的,能独立运行的基本单位。

  • 线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源,但是它可与同属于一个进程的其他线程共享所拥有的全部资源。

  • 一个线程包含以下内容:
    a、一个指向当前被执行的指令指针;
    b、一个栈;
    c、一个寄存器值的集合,定义了一部分描述正在执行线程的处理器状态的值;
    d、一个私有的数据区。

  • 处于同一个进程的所有线程都可以访问该进程包含的地址空间,也包含存储在该空间中的所有资源。

进程用于将资源集中在一起,线程则是在CPU上被调度的实体。

2、多线程的优缺点:

①、多线程的优点:

  • 多线程技术使程序的响应速度更快,因为用户界面可以在进行其他工作的同时一直处于活动状态;
  • 若当前没有进行处理任务,可以将处理器时间让给其他任务;
  • 占用大量处理时间的任务可以定期将处理器时间让给其他任务;
  • 可以随时停止;
  • 可以分别设置各个任务的优先级以优化性能;

②、多线程的缺点:

  • 等候使用共享资源时会使程序运行速度变慢;
  • 对线程的管理要求额外的CPU开销。线程的使用会给系统带来上下文切换的额外负担,当这种负担超过一定程度时,多线程的缺点会表现得较突出;
  • 线程的死锁,即较长时间的等待或资源竞争,以及死锁等多线程症状;
  • 对公有变量的同时的读和写。当多个线程需要对公有变量进行写操作时,后一个线程会改变前一个线程存放的参数,从而导致前一个线程的参数被修改;当公有变量的写操作是非原子性时,在不同的机器上,中断时间的不确定性会导致在一个线程内的操作产生错误。

3、多线程的实现:

①、线程的创建:

pthread_create函数用于创建线程
所在的表头文件:#include <pthread.h>
函数原型:

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

其中,pthread_t *restrict tidp表示要创建的线程的线程ID指针;
const pthread_attr_t *restrict attr表示创建线程时的线程属性;
void *(*start_rtn)(void)表示返回值是void的指针函数,是线程的入口;
void *restrict arg表示往线程中传递的参数,每次传递一个,如果想传递多个,则使用结构体。

②、终止线程:

pthread_exit函数用于终止线程。
所在的表头文件:#include <pthread.h>
函数原型:

void pthread_exit(void *retval);

pthread_exit表示线程主动退出。

③、等待线程终止:

pthread_join函数用于等待线程终止。
所在的表头文件:#include <pthread.h>
函数原型:

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

其中,tid表示要等待的线程ID,指定的线程必须位于当前进程中,而且不得是分离线程。
status用于接收结束线程函数返回的内容。

4、线程属性:

仅当创建新线程的时候,线程属性对象才被参考,同一个线程属性对象可用于创建多个线程,在pthread_create函数之后修改一个线程对象并不会修改之前创建的线程的属性。
线程属性的结构如下:

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函数用于去除初始化。
函数原型:

int pthread_attr_init(pthread_attr_t *attr);
//attr表示线程的属性变量,对线程属性初始化
int pthread_attr_destory(pthread_attr_t *attr);
//attr表示线程的属性变量,对线程属性去除初始化

②、线程分离:

  • 在任何一个时间点上,线程都是可结合或者分离的;
  • 一个可结合的线程能够被其他线程回收资源和杀死,在被其他线程回收之前,它的存储器资源是不释放的;
  • 一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。
  • pthread_attr_getdetachstate函数用于获取线程的分离状态属性,其函数原型为
int pthread_attr_getdetachstate(const pthread_attr_t *attr,int *detachstate);
//attr表示线程的属性变量,detachstate表示线程的分离状态属性
  • pthread_attr_setdteachstate函数用于修改线程的分离状态属性,其函数原型为
int pthread_attr_setdteachstate(pthread_attr_t *attr,int *detachstate);
//attr表示线程的属性变量,detachstate表示线程的分离状态属性

③、线程的继承性:

  • pthread_attr_setinheritsched函数用于设置线程的继承性,其函数原型为:
int pthread_attr_setinheritsched(pthread_attr_t *attr,int inheritsched);
//attr表示线程属性变量,inheritsched表示线程的继承性
  • pthread_attr_getinheritsched函数用于获取线程的继承性,其函数原型为:
int pthread_attr_getinheritsched(const pthread_attr_t *attr,int inheritsched);
//attr表示线程属性变量,inheritsched表示线程的继承性

继承性决定调度参数是从创建的进程中继承还是使用在schedpolicy和schedparam属性中显式设置的调度信息。

④、线程的调度策略:

  • pthread_attr_getschedpolicy函数用于获取线程的调度策略,其函数原型为:
int pthread_attr_getschedpolicy(const pthread_attr_t *attr,int *policy);
//attr表示线程属性变量,policy表示调度策略。
  • pthread_attr_setschedpolicy函数用于获取线程的调度策略,其函数原型为:
int pthread_attr_setschedpolicy(pthread_attr_t *attr,int *policy);
//attr表示线程属性变量,policy表示调度策略。

调度策略的值可能是先进先出(SCHED_FIFO)、轮转法(SCHED_RR)和其他(SCHED_OTHER)。

⑤、线程的调度参数:

  • pthread_attr_getschedparam函数用于获取线程的调度参数,其函数原型为:
int pthread_attr_getschedparam(const pthread_attr_t *attr,struct sched_param *param);
//attr表示线程属性变量,param表示sched_param结构
  • pthread_attr_setschedparam函数用于设置线程的调度参数,其函数原型为:
int pthread_attr_setschedparam(pthread_attr_t *attr,struct sched_param *param);
//attr表示线程属性变量,param表示sched_param结构

5、线程同步机制:

①、互斥锁:

互斥锁用来保护一个或者一些资源。一个线程如果要访问该资源,必须要获得互斥量并对其加锁,这时如果其他线程想要访问该资源也必须要获得该互斥量,但是该互斥量已经加锁,所以这些线程只能阻塞,等待解锁。
互斥操作函数:

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t * mutexattr);//互斥锁初始化
int pthread_mutex_lock(pthread_mutex_t * mutex);//上锁
int pthread_mutex_trylock(pthread_mutex_t * mutex);//在互斥量被锁住时才阻塞
int pthread_mutex_unlock(pthread_mutex_t * mutex);//解锁
int pthread_mutex_destroy(pthread_mutex_t * mutex);//清除互斥锁

如果一个线程已经给一个互斥量上锁,后面的操作又再一次调用了该上锁的操作,那么该线程就会无限阻塞 在这个地方,从而导致死锁。
pthread_mutexattr_settype函数用于设置互斥锁属性,其函数原型为:

int pthread_mutexattr_settype(pthread_mutexattr_t *attr,int kind);
//attr表示声明的属性变量,kind表示要设置的属性类型

②、条件变量:

  • 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁只有锁定和非锁定两种状态的不足。
  • 在使用时,条件变量用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其他的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件阻塞的线程。

条件变量相关函数:

pthread_cond_t cond=PTHREAD_COND_INITIALIZER;//条件变量结构
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t*cond_attr);//初始化条件变量
int pthread_cond_signal(pthread_cond_t *cond);//激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个
int pthread_cond_broadcast(pthread_cond_t *cond);//激活所有等待线程
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);//无条件等待
int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex,const struct timespec *abstime);//计时等待,如果在给定的时刻前其条件没有满足,则返回ETIMEOUT,结束等待。
int pthread_cond_destory(pthread_cond_t *cond);//注销条件变量
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值