【Linux】线程结束

目录

线程安全和重入

死锁

STL中的容器不是线程安全的

线程安全的单例模式

自旋锁

读者写者问题


线程安全和重入

线程安全:多个线程并发执行同一段代码时,不会出现不同的(异常的)结果,我们就说线程是安全的。常见于对全局变量或静态变量进行操作,并且没有锁保护的情况下,会出现该问题

重入:同一个函数被不同的执行流调用,当前一个执行流还没有执行完,就有其他的执行流再次进入,我们就称之为重入。如果一个函数在重入的情况下,运行结果不会出现任何不同或任何问题,则该函数被称为可重入函数,否则叫不可重入函数

线程安全说的是线程在执行中的相互关系,而重入说的是函数的特点,它们其实区别还是很大的,它们之间的关系我们可以理解为下图:

常见的线程不安全的情况

1.不保护共享变量的函数

2.函数状态随着被调用,状态发生变化的函数

3.返回指向静态变量指针的函数

4.调用线程不安全的函数

常见的线程安全的情况

1.每个线程对全局变量或静态变量只有读取的权限,而没有写入的权限,一般来说这些线程是安全的

2.类或者接口对于线程来说都是原子操作

3.多个线程之间的切换不会导致该接口的执行结果存在二义性

死锁

死锁顾名思义就是锁死了,就是说代码不会向下正常推进了,举一个最简单的例子:我们错把unlock仍写成了lock,此时线程就会因为申请不到锁而一直阻塞在这里,当然这只是为了理解什么叫死锁

举一个更加普遍的例子,线程1需要先申请锁1再申请锁2才可以访问资源,线程2需要先申请锁2再申请锁1才可以访问资源,当线程1申请完锁1,线程2申请完锁2后由于它们再也申请不到另一把锁了,所以就会一直阻塞,就会出现死锁问题

由上面的例子我们可以得到产生死锁的四个必要条件

1.互斥条件:一个资源每次只能被一个执行流使用。就是说要加锁

2.请求与保持条件:我既保持我的资源(锁),我还要你的资源

3.不剥夺条件:一个执行流已获得的资源,在未使用完之前,不能强行剥夺。就是说不会去抢别人的锁

4.循环等待条件:线程之间形成一种头尾相连的循环等待资源的关系

上面说的是必要条件,就是如果产生死锁,那么四个条件必然发生,那么我们只要破坏掉其中的一个条件即可

1.破坏第一个条件就是非必要不加锁

2.破坏第二个条件就是不保持条件了,如果拿着锁1,申请不到锁2,那么干脆把锁1也释放掉

3.剥夺别人的锁,释放掉别人的锁

4.尽量不要构成循环等待,每个线程申请锁的顺序要一致

STL中的容器不是线程安全的

因为STL的设计初衷就是为了将性能挖掘到极致,而一旦涉及到加锁保证线程安全,会对性能造成巨大的影响

智能指针是否线程安全?

对于unique_ptr由于只是在当前代码块范围内生效,因此不涉及线程安全问题

对于shared_ptr,多个对象共用一个引用计数变量,所以会存在线程安全问题,标准库实现的时候考虑到了这个问题,基于原子操作保证它是线程安全的

线程安全的单例模式

单例模式就是只创建一个对象,通常有饿汉和懒汉两种方式,饿汉是在主函数加载之前就创建出对象,懒汉是第一次用的时候才创建对象

饿汉是线程安全的,因为程序加载后多个线程只是去获取对象的指针,而懒汉我们则需要通过加锁的方式实现线程安全,那么我们下面可以改写线程池使线程池支持单例模式

我们就是创建静态的对象指针,创建一个静态的获取对象的函数,构造私有化,禁用拷贝构造和赋值重载

自旋锁

自旋其实就是一个不断询问的过程,我们是否用自旋锁就跟线程在临界区中执行时间的长短有关了,如果执行时间长的话,比如有IO操作或者网络请求,我们就用之前学的普通的锁,线程会挂起等待;如果执行时间短,比如都是内存级的操作,我们就可以不必挂起等待,而是不断的询问申请锁

读者写者问题

读者之间没有关系,因为读者跟之前的消费者不同,读者并不会把数据拿走;读者和写者之间是互斥和同步的关系,写到一半不能读,会导致数据不一致的问题;写者之间是互斥关系

他们之间的关系可以用下面的伪代码来表示

我们上面的接口默认就是读者优先的,会有写者饥饿问题

我们如果想让写者优先,可以让没来读的人先别来读了,让正在读的人读完

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值