【内卷套餐】多线程3

原子性:简单说就是需要对应一条汇编代码,多了不行,像变量自增,需要从内存搬运到CPU计算再搬运回来,对应三条汇编操作。

对临界区进行保护,所有的执行线程都必须遵守这个规则。
lock->访问临界区(花时间)->unlock,在特定/进程线程拥有锁,期间有新的线程过来申请锁,它是一定申请不到的,所以会被阻塞,将线程/进程对应的PCB投入到等待队列,unlock之后,进行进程\线程的唤醒操作,放入run队列
所有的线程必须先看到同一把锁,所以锁本身就是临界资源,所以锁必须先保证自己的安全!
申请锁的过程,不能有中间态,lock->原子性,unlock->原子性

该如何理解POSIX phthread中的mutex?
struct mutex {
int lock; //0为被占有,1为可以申请
wait_queue *head 被阻塞的线程队列
}
一次保证只有一个线程进入临界区,访问临界资源,就叫做互斥!

在临界区多行代码中,线程时间片到了,或者优先级等问题,当前线程被切换下去了。
但是没关系,因为持有锁的线程没有做解锁动作,所以临界区仍然在被保护。

加锁为什么一般效率比较低?或者影响效率?
本来是并发执行的执行流,在加锁之后编程了串行;即便是串行情况下,在时间片和优先级等情况下,线程也有可能被切换走,就更慢了。

怎么说明加锁是原子的?

  • CPU寄存器内部会和内存中锁的 01值swap,打个比方,进程1进行加锁操作,它进入CPU寄存器,第一步把它的寄存器值置为0,然后和内存中的锁交换值,此时没有线程访问过锁,所以内存中锁的lock值为0;交换完了之后,lock值变为了0,线程1的寄存器值为1;此时线程2突然切换进来,它同样寄存器置0,但是它swap内存中的同一把锁的时候,此锁的Lock值为0,1已经被上一家线程1交换走了,所以If(lock>0不成立,它只能走else语句被阻塞等待。
  • 在整个过程中,为1的mutex只有一份
  • exchange一条汇编完成了寄存器和内存数据的交换

在这里插入图片描述


说明函数的重入?

当一个函数被多个不同执行流进入,一个执行流还没执行完,另外一个执行流就就来了,我们称之为重入,一个函数在重入的情况下,运行结果如果不会出现任何不同或者任何问题,则该函数被称为可重入函数;否则,为不可重入函数。

线程安全问题

多个线程并发同一段代码时,不会出现不同的结果。在没有锁保护的情况下,如果出现了数据不一致导致其他线程受影响的情况,就叫做线程安全问题。
不可重入函数发生的意外状况就是线程安全问题,他们是互相补充的。

减少线程安全,最好的办法就是减少静态变量和全局变量的使用。 如何函数是可重入的,那执行它的线程就是安全的。
函数是不可重入的,那就不能由多个线程使用,有可能引发线程安全问题。 如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的。


死锁的概念

  • 死锁是指在一组进程中的各个进程均占有不会释放的资源,但因为互相申请被其他进程所占用的不会释放的资源而处于的一种永久等待状态

死锁四个必要条件

  • 互斥条件:一个资源每次只能被一个执行流使用
  • 请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放
  • 不剥夺条件:一个执行流已获得的资源,在末使用完之前,不能强行剥夺
  • 循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系

在这里插入图片描述
自己也有可能会被自己死锁

同步:
在保证数据安全的情况下(一般使用加锁的方式),让多个执行流按照特定的顺序进行临界资源的访问,称之为同步的过程。
这里的同步针对互斥的情况。

为什么要存在同步?
为了多线程协同高效完成某些事情。

如何编码实现?(拿苹果取苹果)
1.如果条件不满足,释放锁,等待。
2.通知机制

pthread_cond_init
pthread_cond_destroy
pthread_cond_wait
pthread_cond_singal

cond
一个线程要在cond上等,一个要把通知信息发到cond
struct cond
{
int value; 条件是否满足,1/0
wait_queue *head; 等待的线程队列
}

在这里插入图片描述
在这里插入图片描述
线程1在等待线程2的cond信号,收到了就printf,也可以有多个线程等待线程2的cond信号,此时就形成了等待队列

生产者消费者模型,本质是生产者把产品放到超市里面,消费者从超市里把产品拿走。
在计算机上,一般是有一段内存空间,有多个线程负责生产,有多个线程负责消费。/所谓产品就是数据
在这里插入图片描述
问题?为什么要有超市?为什么要有特定的消费场所?
为了高效,生产者一次生产一批数据,消费者一次拿走大量数据,效率高
防止消费者找消费者,消费者不方便的尴尬情况
有了超市,相当于大型缓冲区,方便生产者知不知道自己该不该继续生产,生产了有没有地方放。

3钟关系:生产者v生产者 :互斥关系 (缓冲区是临界资源,只能有一个人写)
生产者v消费者 :同步关系(生产完了才能消费,消费完了才能供货)
消费者v消费者 : 互斥关系
2种角色:两种角色,生产者和消费者
1一交易场所

在这里插入图片描述
上图中,main和add函数既可以被看成是是消费者,也可以被看成是生产者,并且main等待add的返回,两者串行,耦合性很强。

在这里插入图片描述
在线程2在计算时候,线程1在写入,可以让他们并行起来,效率提高了。中间的缓冲区相当于超市,一定程度上中和两个线程运行速度


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值