解决的方案
Unix 为我们提供了数种应对的方案。
互斥量(把共享的资源,变成单独享有)
从某种意义上来看,渐序处理往往也意味着在同一个时间内,一个资源一个人用。 而在互斥量方案下,它就成为了一个生动的实践。
互斥量(mutex)实际上就是锁,在一片数据区域加锁以后,其它所有的线程的读写操作,都会被暂时阻塞,直到加锁的线程释放锁。
涉及到的函数,可以参见文章 www.geeksforgeeks.org/mutex-lock-…
(geeksforgeek 上面的流程图示例 涉及两个线程)
值得注意的是死锁问题,我们要看到的事情是,倘若一个线程对同一个互斥量连续加锁两次,那么,该线程自身将会陷入“永久阻塞”状态,同时,如果一组资源如果为不同的进程所占有,但是彼此之间又存在依赖关系,那么,可能会产生死锁问题。
同时,也要看到,对于数据的读写,分门别类,有差有别,对于读一份共享的数据而言,如果数据在短时期内,不发生变化,那么,“让大家都来”比“一个个来”,更加具有效率上的优势。
出于这种情况,读写锁被提了出来。
读写锁(共享互斥锁)
相较于“让大家都等”的互斥量,“读写锁”更加具有一种“分门别类”的智慧,它的做法是:
第一,把面向数据的操作,划分为“读”,“写”两类,并分别设置“读锁”和“写锁”。 第二,对于已经加上了读锁的数据而言,想要访问它进行读取是一件 “立即可行” 的事情,唯一的改变在于计数器会加上一。 第三,写锁具有独享性,一个数据区域,如果加上写锁,那么,其它的读取操作,将被阻塞直到完成释放为止。 第四,为了避免接连不断的读取操作影响写入,在线程提出了写的请求之后,随后的读锁申请,将会被阻塞(大部分情况下,具体取决于实现)。
锁的超时机制
为了避免死锁,我们可以使用一些采用了超时机制的锁函数,这里,我们可以用计算机网络中的有关知识来触类旁通。
- 每间隔一段时间,TCP 连接就会传输一个数据包给目标主机
- 根据应答与否,判断该连接的有效性
- 由此,令死连接不会一直占用资源
而锁的超时机制也与之类似,只不过不同的事情是,因为它发生于锁的申请阶段,所以它只做一次检测。