目录
线程同步之线程互斥-mutex互斥锁和原子类型
添加互斥锁(比较重):锁的获取是由内核来保证的,在多线程环境下,一次只有一个线程获取到锁,其他线程阻塞在这把锁(悲观锁)上,就绪态变成阻塞态,在阻塞队列上,但是不一定非得阻塞:还有trylock(活锁,乐观锁,不会阻塞线程,原地转圈,用在获取时间非常短,频率大)
lock_guard:通过构造加锁,通过析构解锁
unique_lock:提供了lock和unlock的方法,可以和条件变量结合,做一些线程通信的操作
C++11提供的CAS原子类型:基于操作系统的CAS
“无锁机制”,这种锁非常轻量,效率和性能高
适用场景:对共享变量++,- -
线程同步之线程通信-条件变量cond
线程的调度完全没有顺序可言,受内核的调度算法控制。
但是如果有这样的需求场景:
线程执行,如果发现条件不成立,进入等待wait状态,等待条件成立,相当于处于不受调度的状态,不在就绪队列中,如果被通知notify,从等待状态转向阻塞状态,获取到锁,进入就绪队列,收CPU调度了,就可以继续向下执行。
一个线程的代码块依赖于另一个线程的代码块的结果,需要线程间的通知机制。
条件变量:对于线程的通信的控制更加精确
cond.wait()做了两件事:
1.改变了线程的状态:由正常生产变为等待
2.把互斥锁mtx释放了
生产者cond.notify_all()之后,消费者线程从等待状态变为阻塞状态(因为还没拿到锁),生产者线程出了作用域,把锁释放掉,消费者有机会拿到锁,从阻塞状态变为就绪状态
以上描述实现的是场景一,先生产,后消费;如果想要实现场景二的话,while()的条件不是full(),而是size==1
线程同步之线程通信-信号量
信号量比条件变量控制的程度相对来说不精细。
应用场景1:
应用场景2:
进行多线程执行时,遇到了线程间的通信,多线程还需要操作同一个容器,要保证线程安全(原子特性),一般采用条件变量+互斥锁;如果只是想保证两个线程一前一后执行,想要解决时序问题,采用信号量就可以了
应用场景3:
二元信号量(和互斥锁相似,但是有风险):
互斥锁是做线程同步之线程互斥的,信号量是做线程同步之线程通信的
信号量还包含一种二元信号量跟互斥锁是非常相似的,也可以做线程的互斥,但是在使用的过程中有可能存在风险,信号量最终还是属于线程通信的机制,它的post和wait方法可以在不同的线程中调用,可能存在问题。
其他线程可以随意调用wait,post
但是其他线程不可以调用unlock,是非法操作,因为没有获取锁。
项目设计
涉及生产—消费者模型,一个提交到任务队列,一个从任务队列取任务