独占锁和共享锁有啥区别?

Posted

技术标签:

【中文标题】独占锁和共享锁有啥区别?【英文标题】:What's the difference between an exclusive lock and a shared lock?独占锁和共享锁有什么区别? 【发布时间】:2012-08-03 23:08:11 【问题描述】:

根据***,

共享锁有时称为“读锁”,排他锁有时称为“写锁”。

您能解释一下“共享”和“独占”这两个术语背后的原因吗?

【问题讨论】:

非独占锁是共享锁的别称吗? 【参考方案1】:

我写下这个答案是因为我认为这是一个有趣(且恰当)的类比:

将可锁定对象想象为教室中的黑板(可锁定),其中包含教师(作者)和许多学生(读者) )。

当老师在黑板上写东西(排他锁)时:

    没有人可以读取它,因为它还在写,而且她挡住了你的视线 => 如果一个对象被独占锁定,则无法获得共享锁

    李>

    其他老师也不会上来开始写,或者板子变得不可读,让学生感到困惑=> 如果一个对象被排他锁,其他排他锁就无法获得

当学生阅读(共享锁)黑板上的内容时:

    他们都可以一起阅读上面的内容 => 多个共享锁可以共存

    老师等他们读完才清板写更多 => 如果一个或多个共享锁已经存在,则无法获取排他锁

【讨论】:

很好的解释。然而,PO 询问了“共享”和“专有”面额的起源,而不是对它们本身的解释。 这是“如果一个或多个共享锁已经存在,则无法获取排他锁”。是真的?就 ReentrantReadWriteLock 而言?我认为写锁可以随时获得,否则可能会因连续读取而导致写饥饿。 @KanagaveluSugumar,是的,这是真的。当另一个实体已经持有同一个对象的读锁时,您根本无法获得写锁。这就是读写锁的全部意义所在。如果您碰巧在其他人正在阅读某些内容时覆盖了它,那么他们会阅读什么?我不知道您为什么选择专门选择“重入”读写锁,但是重入意味着重入锁的所有者可以再次“锁定()”它以及所有后续@987654322第一个之后的 @ 调用将立即成功返回。即你可以成功锁定你已经拥有的东西。 您还提到“我认为可以随时获得写入锁,否则可能由于连续读取而导致写入饥饿” - 这根本不可能。当某个其他实体已经持有读/写锁时,无法获得写锁。 可以发生的是,如果多个实体已经在等待锁定一个对象,那么当锁选择谁获得锁下一个时,等待的writer 优先于等待的读者>(当它被当前所有者解锁时)。这是关于policy。 谢谢!我选择了 ReentrantReadWriteLock;因为那是java中ReadWriteLock的实现类。那么当写线程开始等待时,是否有任何标志或更多优先级设置来说明更多新的读线程要等待?因为如何避免由于连续读取请求而导致写入线程饥饿?【参考方案2】:

这很简单。读锁也称为共享锁,因为多个进程可以同时读取。读锁的目的是防止另一个进程获取写锁。相比之下,写锁在写操作完成时禁止所有其他操作,这就是它被描述为独占的原因。

所以读锁说“你现在可以读,但是如果你想写,你必须等待”,而写锁说“你必须等待”。


我知道你正在研究以支持你的学习,但我无法抗拒演讲的冲动。

不恰当地使用锁定是导致性能问题的主要原因。使用区分读写锁的锁定系统是一个好的开始,但仔细设计有时可以消除大部分锁定需求。例如,会话状态应该永远保存在每个状态元素的一个全局集合中。

我实际上已经看到这样做了。这是一个糟糕的设计,每次会话状态的最后一次更改都会导致装箱和对集合的更改,从而导致长时间的写锁定。开销非常严重,有效地将服务器减少为单线程行为。

简单地将所有会话状态聚合到一个结构中是一个巨大的改进。对会话状态的更改仅仅改变了会话状态结构成员的值。由于没有其他会话有机会甚至没有机会直接引用会话的状态,因此唯一被更新的集合是会话列表。结果,在会话期间完全不需要锁定,仅在开始和结束时,吞吐量增加了 3000 倍。

另一个常见的锁定场景是用户应用程序的线程之间共享资源。大多数现代框架使用消息而不是锁来解决这个问题。当您“转换到 UI 线程”时,实际上是在排队包含函数指针和一些参数(或委托和堆栈帧,具体取决于实现)的消息。

【讨论】:

【参考方案3】:

独占锁或写锁赋予进程独占访问权限以写入文件的指定部分。当写锁到位时,没有其他进程可以锁定文件的该部分。

共享或读锁禁止任何其他进程在文件的指定部分请求写锁。但是,其他进程可以请求读锁。

更多信息:http://www.gnu.org/software/libc/manual/html_node/File-Locks.html

【讨论】:

【参考方案4】:

数据库端的原理也是一样的。根据 Oracle 文档

独占锁定模式可防止相关资源被共享。获得这种锁定模式是为了修改数据。第一个独占锁定资源的事务是唯一可以更改资源的事务,直到独占锁定被释放。

共享锁定模式允许共享相关资源,具体取决于所涉及的操作。读取数据的多个用户可以共享数据,持有共享锁以防止写入者(需要排他锁)并发访问。几笔交易可以 获取同一资源的共享锁。

【讨论】:

以上是关于独占锁和共享锁有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

Java并非锁之独占非公平锁理解

AQS共享锁和独占锁

并发编程—独占锁和共享锁

实现一个独占锁和3元共享锁及其思路

mysql的独占锁和共享锁

理解AbstractQueuedSynchronizer提供的独占锁和共享锁语义