和朋友聊天他提到:ReentrantLock 的构造函数可以传递一个 bool 数据,true 时构造的是“公平锁”、false 时构造的是“非公平锁”。
英吉沙网站建设公司创新互联公司,英吉沙网站设计制作,有大型网站制作公司丰富经验。已为英吉沙成百上千家提供企业网站建设服务。企业网站搭建\成都外贸网站制作要多少钱,请找那个售后服务好的英吉沙做网站的公司定做!
我的印象中锁是不区分类型的,所以认为这应该是 Java 发明的概念,于是就恶补了一下。
锁的底层实现
无论什么语言在操作系统层面锁的操作都会变成系统调用(System Call),以 Linux 为例,就是 futex 函数,可以把它理解为两个函数: futex_wait(s),对变量 s 加锁;futex_wake(s)释放 s 上的锁,唤醒其他线程。
如果你熟悉操作系统原理其实就是 P/V 操作。
Java 公平锁和非公平锁
公平锁的 lock 操作是调用futex_wait,unlock 操作是调用futex_wake。比如下面的代码
非公平锁的 lock/unlock 操作会先做一次 CAS 操作然后再调用 futex_wait、futex_wake。比如下面的代码
在上锁之前增加了一个 CAS 原子操作,它接受三个变量可以把它理解为下面的逻辑:
***个参数的值和第二个参数不相等则返回 0 表示操作失败否则更新为新的值。这个函数不是由代码实现的而是 CPU 提供的一个指令,比如 Intel 的叫 cmpxchg;高级语言进行了封装,比如 Java 的 Atomic 变量。
为什么
明白了原理再来提问为什么,在上锁之前先通过 CAS 修改一个变量表示“我要上锁”了看似很冗余的操作,其实它是一次自旋,如果资源很快被使用完可以提高系统的吞吐率。考虑下面的场景
上锁之前的时间是 t1,上锁之后是 t2(使用资源),释放锁是 t3。
现在有两个线程,处于 t1 状态,其中 A 线程先抢到资源处于 t2 ;B 线程也会尝试 lock,与此同时 t2 释放了,而 lock 动作也执行成功了 B 被挂起;系统继续执行 A 释放成功唤醒 B 继续执行。
上述过程中 B 只要再多等待“一丢丢”就不用被挂起,直接获得资源继续执行。非公平锁的 CAS 操作就是为了增加一丢丢时间。
采用非公平锁,如果系统中有 3 个线程执行,A 抢到资源,C 没有抢到处于挂起状态,此时 B 尝试 CAS 操作,而 A 刚好释放掉资源还没有来得及唤醒 C,那么 B 会先抢到资源,在 C 之前执行。这就是“非公平”的来历,虽然 C 老老实实的等待了很长时间,但是 B 的“时机”把握的好,迅速“插队”完成资源抢占。
总结
上锁的过程本身也是有时间开销的,如果操作资源的时间比上锁的时间还短建议使用非公平锁可以提高系统的吞吐率;否则就老老实实的用公平锁。
【本文是专栏作者“邢森”的原创文章,转载请联系作者本人获取授权】
戳这里,看该作者更多好文
分享名称:一分钟理解Java公平锁与非公平锁
网站路径:http://www.36103.cn/qtweb/news37/17587.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联