同步:主要是为了解决访问临界资源合理性问题的(如抢票的时候不能只让一个进程把所有的票抢走),同步是按照一定的顺序,进行临界资源的访问。
条件变量
申请临界资源前,先检测临界资源是否存在,要做检测的本质:也是访问临界资源!因此:对临界资源的检测,也一定是在加锁和解锁之间的。常规方式要检测条件就绪,就注定了我们必须频繁申请和释放锁。
有没有办法让我们的线程检测到资源不就绪的时候?
不要让线程再频繁自己检测啦,让线程进行等待。
当条件就绪的时候,通知对应的线程,让他来进行资源申请和访问。
当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。
例如一个线程访问队列时,发现队列为空,它只能等待,直到其它线程将一个节点添加到队列中。这种情
况就需要用到条件变量。
同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问
题,叫做同步
竞态条件:因为时序问题,而导致程序异常,我们称之为竞态条件。在线程场景下,这种问题也不难理解
初始化pthread_cond_init

如果定义的是全局的,静态的可用最下面的PTHREAD_COND_INITIALIZER
如果定义的是局部条件变量,用第二个进行初始化
等待某种条件pthread_cond_wait

pthread_cond_timedwait多了一个timespec参数这个表示时间,这是设置等待时间的,这个接口我们了解即可。
pthread_cond_wait是在特定的条件变量下去等,这里面参数多了个互斥锁,这个锁的起到一定的安全作用(要保证同步和互斥),第一个参数是让线程在特定的条件变量下(我们可理解为变量),第二个是锁
发送通知pthread_cond_signal

第一个接口相当于不止有一个线程在等资源就绪,broadcast作用是把所有线程全部唤醒。
第二个接口是唤醒指定的一个线程。
使用接口小实验
我们创建多个线程,其中有一个主线程,主线程会按照一定的顺序唤醒其它线程。





单个线程唤醒
接下来我们想让哪个线程去运行,就唤醒哪个线程,我们去掉4个线程的sleep




我们发现线程是按照顺序唤醒的,因为这些线程在条件变量不满足时,此时会在该线程下排队等待,因此主线程在唤醒线程时会一个一个唤醒。因为是队列,所以有序。
我们也可以唤醒一批线程


进行10次唤醒线程
接下来我们唤醒线程10次,之后让系统整体全部退出。
我们设计一个标志位和cnt计数,并修改func函数里面的while循环



10次循环结束后,我们发现程序卡住了

换用broadcast,同样唤醒10次后,程序也卡住了


出现这种现象是因为我们写的这部分代码是不全面的

这里的wait一定要在加锁和解锁之间进行wait,而且主线程这里要进行一次唤醒
此时程序运行正常


