线程的基础

本文详细介绍了线程与进程的区别,强调线程作为调度的基本单位和进程作为资源分配的最小单位。线程共享进程资源,拥有私有资源如TCB,多线程引入以实现更高效的资源利用。线程通信相对简单,但需处理临界资源访问,而进程通信更为复杂。线程同步包括mutex锁、条件变量和信号量,用于保证临界资源的安全访问。文中还展示了相关API的使用示例。
摘要由CSDN通过智能技术生成

线程是执行的基本单位,每个线程都有自己的tid,有自己的TCB,如果说进程中只有一个线程,那么这个线程就是进程的主线程,线程共享进程的资源,也有自己私有的资源

进程和线程区别:

共性:都为操作系统提供了并发执行能力

不同点:

调度和资源:线程是系统调度的最小单位,进程是资源分配的最小单位

地址空间方面:同一个进程创建的多个线程共享进程的资源;进程的地址空间相互独立

通信方面:线程通信相对简单,只需要通过全局变量可以实现,但是需要考虑临界资源访问的问题;进程通信比较复杂,需要借助进程间的通信机制(借助3g-4g内核空间)

安全性方面:线程安全性差一些,当进程结束时会导致所有线程退出;进程相对安全

那么什么是私有资源,多任务可以使用多进程实现,为什么要引入多线程呢?

 两个进程交流通讯需要调用系统内核,两线程之间则不需要,但是线程中的临界资源当两线程同时访问是会互相打扰,因为线程是异步的,因此要锁住线程,或者让他们称为同步的原子操作

#include<pthread.h>

int pthread_create(pthread_t*thread,const pthread_attr_t*arr,void*(*srart_route)(void*),void*arg);

功能:创建一个新线程

参数:

thread:将新线程的id存储到这个地址空间

attr:NULL,使用缺省属性

arg:传递给线程函数的唯一参数

start_route:函数指针指向函数的入口地址(线程函数)

返回值:

成功返回0

失败返回非零数字,errno被设置

注:编译时要链接-pthread库 

pthread_t pthread_self(void);

功能:获取当前线程的ID

返回值:返回当前线程的tid(unsigned long类型)

线程的终止、汇合和分离

①终止

pthread_exit(void*retval);

功能:终止当前县城

参数:

retval:通过此参数,将线程的退出状态码传递给进程中调用

无返回值

②进程的汇合和分离

 int phread_detach(pthread_t thread);

功能:分离一个线程

参数:线程id

返回值:成功返回0,失败返回非零,errno被设置

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

功能:汇合一个已终止的线程(阻塞等待)

参数:

thread:指定了要汇合的线程id

**retval:将可汇合的线程的退出状态码拷贝到*retval中,如果是取消的线程,将PTHREAD_RANCELED放到*retval中

③线程的取消

int pthread_cancel(pthread_t thread);

功能:发送一个取消请求给指定的线程

参数:

thread:指定要取消的线程id

返回值:成功返回0,失败返回非零,errno被设置

可重入函数:只能访问自己的栈帧内容,每一次调用都是独立栈帧

不可重入函数:如果函数访问了自己栈帧以外的空间,例如访问了malloc,全局变量,静态局部变量等

代码演示:

线程同步

mutex锁、条件变量和POSIX信号量

线程访问临界资源时会互相打扰,这些工具就是为了一次只有一个线程来访问临界资源,一个线程访问完成后,下一个线程再来访问

看一段代码:

 所以我们要在访问共享资源的地方给它编程原子操作,必须把它作为整体执行才可以

mutex锁:是一个互斥设备,用于同时修改共享数据时对共享数据的保护

①加锁成功,访问数据,解锁

②加锁失败,等待(或者不等待返回错误)

两种状态:locked和unlocked

创建一个mutex锁:pthread_mutex_t

用mutex锁等于PTHREAD_MUTEX_INITIALIZER也可以实现初始化

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t*restrict attr);

功能:使用缺省属性初始化mutex

参数:

mutex:指定要初始化的mutex

attr:NULL,使用缺省属性初始化mutex锁

返回值:成功总是0;失败会返回errno

int pthread_mutex_destory(pthread_mutex_t*mutex);

功能:当处于解锁状态下,销毁mutex锁

参数:mutex指定被销毁的mutex锁

返回值同上

int pthread_mutex_lock(pthread_mutex_t*mutex);

功能:如果mutex锁目前是unlocked状态,当前进程锁定此锁,立即返回

           如果mutex锁已被其他线程锁定,当前线程挂起直到锁被解除

参数:指定要操作的mutex锁

返回值同上

int pthread_mutex_trylock(pthread_mutex_t *mutex);

功能:与lock一样,只是如果已经锁定,立即返回,并返回EBUSY

返回值同上

int pthread_mutex_unlock(pthread_mutex_t*mutex);

功能:解锁,此锁一定是被当前线程占有并锁定的

参数:mutex指要解除的锁

返回值同上

用mutex锁修改上述代码

 

条件变量(pthread_cond_t类型)

同步设备,允许多线程挂起执行直到条件被满足

#include<pthread.h>

int pthread_cond_init(pthread_cond_t*cond,pthread_condattr_t*cond_attr);

功能:使用缺省属性初始化条件变量

参数:

cond:要初始化的条件变量

cond_attr:NULL缺省属性

返回值:

成功返回0

失败返回非零,errno被设置

让条件变量等于PTHREAD_COND_INITIALIZER这个宏也可以初始化

int pthread_cond_destory(pthread_cond_t*cond);

功能:销毁条件变量,无线程等待的情况

参数:cond要销毁的条件变量

int pthread_cond_wait(pthread_cond_t*cond,pthread_mutex_t*mutex);

功能:

①原子的解锁等待条件变为真

②mutex必须在pthread_cond_wait调用前处于locked状态

③函数返回前,必须重新锁定mutex锁

参数:

cond:指定要操作的条件变量

mutex:使用到的mutex锁

int pthread_cond_timedwait(pthread_cond_t*cond,pthread_mutex_t*mutex,const struct timespec*abstime);

功能:和wait相同,只是指定了一个等待周期,如果过期条件变量还没变为真,重新获取mutex锁,返回ETIMEOUT       

int pthread_cond_signal(pthread_cond_t*cond);

功能:从因此条件变量阻塞的线程中取出一个解除阻塞,如果没有则什么也不发生

参数:

cond:指定条件变量

int pthread_cond_broadcast(pthread_cond_t*cond);

功能:所有因此条件变量阻塞的线程都会被解除阻塞,如无线程等待条件为真,则什么也不做

参数:cond指定具体的条件变量

用代码来看一下:

POSIX 信号量(>=0)整数

可以将临界资源在分割成多个区域,这样多个执行流需访问临界资源时,可以让这些执行流同时访问临界资源的不同区域,此时就不会出现数据不一致的问题,信号量本质也是一种临界资源

申请信号量(P)-1操作

释放信号量(V)+1操作

信号量的PV操作必须是原子操作

 

#include<semaphore.h>

int sem_init(sem_t*sem,int pshared,unsigned int value);

功能:初始化一个匿名信号量地址

参数:

sem:要初始化的信号量

pshared:传入0表示线程间共享,非零表示进程间共享

value:信号量的初始值

返回值:

成功返回0

失败返回-1,errno被设置

int sem_destroy(sem_t*sem);

功能:销毁一个匿名信号量

参数:

sem:指定要销毁的匿名信号量地址

返回值:同上

int sem_post(sem_t*sem);//V操作,信号量值+1操作,信号量为0将阻塞,大于0时唤醒进程

int sem_wait(sem_t*sem);//P操作,信号量-1操作,信号量为0将阻塞,大于0时唤醒进程

int sem_trywait(sem_t*sem);//尝试P操作

int sem_timedwait(sem_t*sem,const struct timespec*abs_timeout);//超时等待

用代码来看一下

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值