线程安全与同步互斥

线程安全的实现:同步与互斥
同步:通过条件判断实现对资源访问的合理性
互斥:通过同一时间只有一个执行流能够访问资源,实现资源访问的安全性

互斥的实现—>互斥锁
互斥锁概念:就是一个 只有0/1的计数器,描述临界资源的两种访问状态(可访问/不可访问),一个执行流在访问期间需要将资源状态标记为不可访问,访问完毕后,将状态标记为可访问,这些访问同一临界资源的执行流都要在访问资源之前,先去访问互斥锁判断访问状态

过程

1.定义互斥锁变量:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER

2.初始化互斥锁变量:int pthread_mutex_init (pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr )

3.在访问临界资源前先加锁:pthread_mutex_lock( pthread_mutex_t *mutex)---如果不能加锁则阻塞等待 ;pthread_mutex_trylock( pthread_mutex_t *mutex )---如果不能加锁则报错返回                                                                                            

4.访问完成之后解锁:int pthread_mutex_unlock( pthread_mutex_t *mutex )

5.销毁互斥锁,释放资源:int pthread_mutex_destory ( pthread_mutex_t *mutex )

注意
1.加锁保护的永远只有临界资源的操作,尽量不要保护其他不相干的,因为加锁之后增加了保护时间,降低了程序效率
2.加锁和解锁成对出现,加锁之后要在任意有可能退出的位置解锁
3.互斥锁只能保护资源访问的安全性,不能保证访问资源的合理性
4.所有的线程访问同一临界资源,必须访问同一个互斥锁进行保护

同步的实现—>条件变量
条件变量概念理解:提供了一个pcb等待队列,提供了两个接口(一个让线程等待,一个唤醒线程),但是这个条件变量实现同步时,自身并没有提供条件判断的接口,也就是说条件变量也不知何时让线程休眠何时唤醒线程
条件变量的条件判断:使用循环判断,被唤醒加锁成功后重新判断是否满足条件

过程

1.定义条件变量:pthread_cond_t cond= PTHREAD_COND_INITIALIZER

2.初始化条件变量:int pthread_cond_init ( pthread_cond_t *restrict cond ,const pthread_condattr_t *restrict arrt )

3.等待条件满足:int pthread_cond_wait ( pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex )---->阻塞等待(这个接口要搭配互斥锁一起使用);int pthread_cond_timewait ( pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespace *abstime ) --->限制阻塞时间,等待超时会报错返回ETIMEOUT
mutex=1-->均未进入;mutex=0-->有一个进入;mutex=-1-->一个进入一个等待

4.唤醒等待:int pthread_cond_broadcast ( pthread_cond_t *cond )--->唤醒所有执行流pcb;int pthread_cond_signal ( pthread_connd_t *cond )--->至少唤醒一个执行流

5.不使用则释放:pthread_cond_destroy ( pthread_cond_t *cond ) 

注意:一个条件变量只有一个pcb等待队列,有可能出现唤醒角色错误的情况,因此应在具有多个角色的情况下使用多个条件变量,不同的角色等待在不同的pcb队列中,避免角色错误问题

可重入和线程安全
重入概念:同一个函数被不同的执行流调用,当一个流程还没有执行完,就有其他流程再次进入,称之为重入。若一个函数在重入的情况下,不会出现任何问题,则该函数称为可重入函数,否则就是不可重入函数
常见的不可重入情况:1.调用malloc函数。2.调用标准I/O库函数
常见可重入情况:1.不使用全局变量或者静态变量。2.不使用malloc和new函数。3.不返回静态或者全局数据。4.使用本地数据

可重入与线程安全的联系
1.函数是可重入,则一定是线程安全
2.函数是不可重入,就有可能有线程安全问题
3.如果一个函数中有全局变量,则这个函数既不是线程安全的,也不是可重入的

可重入和线程安全的区别
1.可重入 函数是线程安全函数的一种
2.线程安全不一定是可重入的,可重入的一定是线程安全的
3.加锁安全,但要是未释放锁,就导致了不可重入

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值