多线程间的同步与互斥

多线程与临界区

多线程想要访问临界区时,就要对临界区进行上锁,这与之前写到的进程互斥是一个道理,这也就是防止共享数据被并发访问的解决方法,这种上锁叫做互斥锁

互斥锁

互斥锁以排他的方式保护共享数据被并发访问。
多线程间的同步与互斥_第1张图片

因为在线程中,内存地址空间是共享的,就像一个大房子,在这个进程中的线程们都可以进来,当我们某一个线程想做一些事时,不想让其他线程打断,那我们就给门上加个锁,当一个进程进来后,把门锁上,当干完想干的事时,再解锁出去,让其他进程进来,这样就保证在做一件事时绝对不会被打断,当其它进程进来时,同样可以做自己想做的事情,可以是与之前进程一样的事情

互斥锁是一个二元信号量


互斥锁的基本操作

多线程间的同步与互斥_第2张图片


条件变量

条件变量基本原理:
互斥锁能够解决资源的互斥访问,但有些情况,互斥并不能解决。

例如下面这种情况,系统有全局变量 i 和 j,线程A和B都要访问,线程A需要互斥的执行i++;j–操作;线程B需要互斥的在 i 等于 j是执行do_something()函数。
多线程间的同步与互斥_第3张图片
如果只使用互斥锁,可能导致do_something()永远不会执行,因为当i=j=5时,线程B不一定能抢占到资源
所以,需要某个机制来解决此问题,更重要的是,线程B仅仅只有一种情况需要执行do_something()函数,但不停的申请释放互斥锁将造成资源的浪费。
在使用互斥锁时结合条件变量解决这一问题。
多线程间的同步与互斥_第4张图片
这里要注意的是,条件变量不能单独使用,必须配合互斥锁一起实现对资源的互斥访问。


条件变量的基本操作

多线程间的同步与互斥_第5张图片
初始化和销毁没有什么好说的,man一下,全清楚
那就说说signal和wait,
wait是在等一个它要等的人(条件),这个人就是signal,signal会发一个信号,当signal发出消息,wait就可以继续执行自己的事情,否则它就一直等待

还是用生产者消费者的例子来看
多线程间的同步与互斥_第6张图片
生产者在生产时要上锁保证自己的生产不被打断,消费者也是一样,但是消费者需要在生产者生产后,才能进行消费所以当生产者生产后要通知一下,消费者也要等着生产者的信号
其实这就像在食堂吃饭时,我们买好饭然后就等着食堂阿姨做好了叫我们,然后阿姨(生产者)去做饭,阿姨做好饭后会叫我们


互斥锁与条件变量的应用
创建相关变量

多线程间的同步与互斥_第7张图片

生产者

多线程间的同步与互斥_第8张图片

消费者

多线程间的同步与互斥_第9张图片
消费者这里有一个小的隐含知识:pthread_cond_wait当前应该是阻塞在这里的,又没有释放锁,那是如何让生产者生产的?
答:如果某线程因等待条件变量进入等待状态时,将隐含释放当前的锁,同样,在返回时,再隐含申请到该互斥锁对象。一会儿我们可以从结果上看到

main

多线程间的同步与互斥_第10张图片

结果多线程间的同步与互斥_第11张图片


读写锁

读写锁基本原理:
在对数据的读写应用中,很多情况是大量的读操作,二较少的写操作,例如对数据库系统数据的访问,显然,这时使用互斥锁将非常影响效率。为了满足这一情况,posix线程提供了读写锁机制
多线程间的同步与互斥_第12张图片


读写锁的基本操作

多线程间的同步与互斥_第13张图片


你可能感兴趣的:(Linux)