首页 > 编程知识 正文

消息队列的特点,linux下读写锁

时间:2023-05-06 20:28:06 阅读:145291 作者:4335

读写锁保持了一对锁、一个读锁和一个写锁,并将读锁和写锁分开,与普通排他锁相比,同时性有了很大的提高。 如果不支持读/写锁定(Java5或更早版本),则需要Java通知等待机制才能完成读/写操作。 也就是说,写入操作开始后,写入操作之后的所有读取操作都处于等待状态。 等待的读取操作在写入操作完成并被通知之前无法继续。 写入操作依赖同步进行同步。 如果改为使用读/写锁定,则只需在读取操作时获取读取锁定,在写入操作时获取写入锁定即可。 后续的读写操作将被阻止,并在释放写入操作后继续执行所有操作。 与等待通知的结构相比,编程方式更简单了。

读写锁定支持公平性选择的重新访问; 国际封锁。

锁降级

为什么要锁降级?

由于对数据敏感,线程需要在对数据修改以后, 获取到修改后的值, 并进行接下来的其它操作之后只需读取data。 如果还在继续使用写锁定,则无法同时读取到多个线程中,拥有写锁定会浪费资源,降低整体效率。 此时,利用锁降级是一个好方法,可以提高整体性能。

锁降级的实现

“封锁”是指保留当前拥有的写锁定,在获取读锁定后释放以前拥有的写锁定。

锁降级中读锁的获取是否必要?

需要答案。 主要为了保证数据的可见性,假设当前线程在未获取读锁定的情况下直接释放写锁定,则当前另一线程t获取了写锁定并修改了数据,那么当前线程无法感知线程T的数据更新(是说线程A使用数据时,并不知道别的线程已经更改了数据,所以使用的是线程T的修改结果。因此通过锁降级来保证数据每次修改后的可见性)当前线程获取读锁定线程t被阻止,在当前线程使用数据解除读锁定之前,线程t无法获取写锁定并更新数据。 也就是说,写锁定和读锁定代码块中的操作相当于用同步关键字限定的代码块,以确保串行执行。

参考:

在ReentrantReadWriteLock中理解封锁

锁升级

ReentrantReadWriteLock不支持锁定升级(保留读锁定、获取写锁定和最后释放读锁定的过程)。 它还旨在保证数据的可视性。 如果读锁定已被多个线程获取,并且其中任何线程获取了写锁定并更新了数据,则该更新对于其他获取的读锁定的线程数不可见。

读写锁定的特征在于,如果线程都申请了读取锁定,则多个线程可以同时具有,但在写入锁定的情况下,已知只能具有一个线程,读取锁定和写入锁定不能同时具有由于读锁定和写锁定不会同时保持,因此在升级写锁定时,必须进行升级直到释放所有读锁定。

假设有三个线程: a、b和c,它们已经有读锁定。 线程a试图从读锁定升级到写锁定。 必须等待b和c释放获取的读取锁定。 随着时间的推移,如果b和c逐渐释放读锁定,则线程a将成功升级并获得写锁定。 但是,我们会考虑特别的情况。 假设线程a和b都想升级到写锁定,则对于线程a,必须等待包括线程b在内的所有其他线程解除读锁定。 线程b也必须等待所有线程,包括线程a解除读锁定。 这是非常典型的死锁情况。 每个人都不想率先释放自己手中的钥匙。

但是读写锁的升级不是不可能的,也有可以实现的方案。 如果保证一次只能升级一个线程,就可以保证线程安全。 但是,最常见的ReentrantReadWriteLock不支持这一点。

参考:

面试官:你知道读写锁吗? 他的升降级什么时候用?

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。