java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > synchronized重量级锁

Java中的synchronized重量级锁解析

作者:爱coding的同学

这篇文章主要介绍了Java中的synchronized重量级锁解析,内核需要去申请这个互斥量,必须要进入内核态,也就是这里需要用户态,内核态的切换,状态的切换,开销是比较大的,这就是重型锁的一个弊端,需要的朋友可以参考下

1. 背景

在JDK1.6以前,synchronized 的工作方式都是这种重量级的锁。它的实现原理就是利用 kernel 中的互斥量,mutex。主要是内核中的mutex 能够保证它是一个互斥的量。如果线程1拿到了 mutex,那么线程2就拿不到了。这是内核帮我们保证的。

至于为什么可以,可以去了解一下内核中的互斥量。

2. 为啥叫做重量级锁

内核需要去申请这个互斥量,必须要进入内核态。也就是这里需要用户态,内核态的切换。状态的切换,开销是比较大的。这就是重型锁的一个弊端。对于重型锁的一些主要的封装都是在 c 语言中的 pthread 这样一个库中,比如mutex_init, mutex_lock 等。之所以叫重量级锁,就是因为需要进入到内核态。

3. 能否在用户态实现一把互斥锁

我们不需要进入到内核态就能够获取到这样的一把锁,也就是在用户态就可以实现一把锁。

比如说,现在就有一把锁,就叫做 state。0:表示未被使用,1 表示锁被占用了。

lock 的实现

在这里插入图片描述

如果锁当前是被占用的状态,那么程序就一直死循环。如果某个时刻,有一个线程把锁释放了,那么就退出死循环,执行下一行 state = 1。而且持有者=当前线程。也就是 state = 0的时候,就可以任务当前线程可以拿到这把锁了。

unlock 的实现

在这里插入图片描述

释放锁的时候,首先需要判断一下当前持有锁的线程是不是当前线程。如果是当前线程,那么就将 state 置为0, 持有者 = null。

当前设计方式存在的问题

while(state==1); state = 1;其实可以认为这个是比较赋值俩步操作,先比较,符合条件了,再进行赋值。那么其实这不是原子性的。比如说在比较的时候,俩个线程同时进行了比较,这俩个线程同时发现state = 0,那么这俩个线程同时都去会执行 state = 1的操作,这俩个线程都认为自己拿到了锁,那么这个就产生了并发的问题了。

如何改进这个问题呢?

我们看到比较和赋值不是原子性的,在软件层面,我们也无法保证这俩步的原子性。所以,计算机给我们提供了原语,也就是 CAS。=

在这里插入图片描述

那么我们来看一下如何改进呢? 我们把比较赋值这俩步操作,变成了一个原语操作,CAS。比较并交换。CAS中有三个参数,cas(state,0,1)。比较state的当前值是不是0,如果是0,那么就赋值为1。

在这里插入图片描述

再看看一下 unlock的操作。 在unlock操作中,其实也是一个比较赋值的操作,首先判断当前持有者是不是当前线程,如果是,再进行赋值。

那为什么这里不需要用cas呢?因为必定是持有锁的线程才能执行到下一行。

而且赋值操作中,先赋值 持有者 = null。再赋值 state = 0。

因为如果先执行 state = 0, 那么就相当于先释放掉这把锁了,另外一个线程就会执行 lock 成功,拿到锁,持有者 = 当前线程。

那么就可能会带来一些问题。因为此时释放掉的锁并不是当前线程持有的锁。

这种锁也叫做自旋锁。

自旋锁的优点与缺点

自旋锁,spinLock。自旋锁不需要进入到内核态,整个程序的执行都是在用户态的,包括cas。但是cas不是计算机的原语吗?因为计算机的指令和用户态,内核态没有关系。

自旋锁当然也有缺点。 lock 操作如果一直没有拿到锁的话,会一直尝试。这是需要消耗cpu资源的。 所以自旋锁对于锁竞争比较激烈的情况下,是不适用的。

总结

mutex锁和自旋锁各有优缺点,那么我们能不能把这俩者结合一下呢?

JDK 1.4 以前是借助内核中的 Mutex 互斥量; JDK1.4 以后是利用自旋锁,自旋n次以后,还是没有拿到锁的话,就切换到mutex。

也就是将自旋锁和mutex进行了一个结合。因为mutex 加锁失败以后,会挂起,让出cpu资源。这样的话,算是对资源的一个合理利用。

JDK1.4以前,我们是可以设置自旋次数的,但是1.6以后,JDK可以自适应自旋,不用设置这个参数了。

当然现在我们所说的都是重量级锁。包括mutext, 自旋锁,自适应自旋锁。

到此这篇关于Java中的synchronized重量级锁解析的文章就介绍到这了,更多相关synchronized重量级锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文