【JUC系列】Java的锁机制
偏向锁/轻量级锁/重量级锁
重量级锁会造成 CPU 在用户态和核心态之间频繁切换,所以代价高、效率低。JDK1.6 版本为了减少获得锁和释放锁所带来的性能消耗,引入了“偏向锁”和“轻量级锁”实现。所以,在 JDK1.6 版本里内置锁一共有四种状态:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态,这些状态随着竞争情况逐渐升级。内置锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。这种能升级却不能降级的策略,其目的是为了提高获得锁和释放锁的效率。
1. 无锁状态
2. 偏向锁状态
3. 轻量级锁状态
4. 重量级锁状态
轻量级锁的很总要一个实现基础就是CAS操作(自旋):
CAS(Compare and swap),即比较并交换,也是实现我们平时所说的自旋锁或乐观锁的核心操作。
- 执行函数:
CAS(V,E,N)
其包含3
个参数
- V 表示要更新的变量
- E 表示预期值
- N 表示新值
如何要更新的变量等于预期值,就把新值赋值给变量,如何要更新的变量不等于预期值,就CAS
再重新试一下,再试的时候,会重新读取要更新的变量作为预期值
比方说:
当前的这个线程想改这个值,我期望你是0
,你就不能是1
;如果是1
,那就说明我这个值不对,然后想把你变成1
。大概就是:原来这个值是变为3
了,我这个线程想修改这个值的时候我一定期望你现在是3
,是3
我才改,如果在我修改的过程你变4
了,说明就有另外一个线程修改过该值,那我cas
就再重新试一下,再试的时候,我希望你的这个值是4
,在修改的时候期望值是4
,没有其它线程修改该值,那好我给你改成5
,这样就是cas
操作。
CAS 实现自旋锁
既然用锁或 synchronized 关键字可以实现原子操作,那么为什么还要用 CAS 呢,因为加锁或使用 synchronized 关键字带来的性能损耗较大,而用 CAS 可以实现乐观锁,它实际上是直接利用了 CPU 层面的指令,所以性能很高。
上面也说了,CAS 是实现自旋锁的基础,cas
是cpu
的原语支持,也就是说cas
是cpu
指令级别上的支持,中间不能被打断,不会造成所谓的数据不一致问题,以达到锁的效果,至于自旋呢,看字面意思也很明白,自己旋转,翻译成人话就是循环,一般是用一个无限循环实现。这样一来,一个无限循环中,执行一个 CAS 操作,当操作成功,返回 true 时,循环结束;当返回 false 时,接着执行循环,继续尝试 CAS 操作,直到返回 true。
其实 JDK 中有好多地方用到了 CAS ,尤其是 java.util.concurrent
包下,比如 CountDownLatch、Semaphore、ReentrantLock 中,再比如 java.util.concurrent.atomic
包下,相信大家都用到过 Atomic* ,比如 AtomicBoolean、AtomicInteger 等。
这里拿 AtomicBoolean 来举个例子,因为它足够简单。
public class AtomicBoolean implements java.io.Serializable {private static final long serialVersionUID = 4654671469794556979L;// setup to use Unsafe.compareAndSwapInt for updatesprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static {try {valueOffset = unsafe.objectFieldOffset(AtomicBoolean.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile int value;public final boolean get() {return value != 0;}public final boolean compareAndSet(boolean expect, boolean update) {int e = expect ? 1 : 0;int u = update ? 1 : 0;return unsafe.compareAndSwapInt(this, valueOffset, e, u); //这里cas,会触发cpu指令}}
ABA问题
CAS 存在一个问题,就是一个值从 A 变为 B ,又从 B 变回了 A,这种情况下,CAS 会认为值没有发生过变化,但实际上是有变化的。对此,并发包下倒是有 AtomicStampedReference 提供了根据版本号判断的实现,可以解决一部分问题。
参考文章:我们常说的 CAS 自旋锁是什么 - 风的姿态 - 博客园
【JUC系列】Java的锁机制相关推荐
- java锁的概念,Java ReentrantLock锁机制概念篇
分享Java锁机制实现原理,细节涉及volatile修饰符.CAS原子操作.park阻塞线程与unpark唤醒.双向链表.锁的公平性与非公平性.独占锁和共享锁.线程等待await.线程中断interr ...
- JUC多线程:synchronized锁机制原理 与 Lock锁机制
前言: 线程安全是并发编程中的重要关注点,造成线程安全问题的主要原因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同操作共享数据.因此为了解决这个问题,我们可能需要这样一个方案,当存在多 ...
- Java基础-锁机制
Java中的锁机制 Lock不是Java语言内置的, synchronized是Java语言中的关键字, Lock是一个接口,通过这个接口可以实现同步访问. Lock允许更灵活的结构, 并可以支持多个 ...
- [java多线程] - 锁机制同步代码块信号量
在美眉图片下载demo中,我们可以看到多个线程在公用一些变量,这个时候难免会发生冲突.冲突并不可怕,可怕的是当多线程的情况下,你没法控制冲突.按照我的理解在java中实现同步的方式分为三种,分别是:同 ...
- java线程锁机制_多线程之锁机制
前言 在Java并发编程实战,会经常遇到多个线程访问同一个资源的情况,这个时候就需要维护数据的一致性,否则会出现各种数据错误,其中一种同步方式就是利用Synchronized关键字执行锁机制,锁机制是 ...
- JAVA之JUC系列 - JAVA内存模型
Java内存模型(简称JMM),定义了线程本地内存和主内存之间的关系,理解JMM的特性,对深入理解Java多线程中内存的可见性会有很大帮助.下面我们从并发编程模型中关注的两个问题说起. 一. 并发编程 ...
- Java的锁机制--偏向锁、轻量锁、自旋锁、重量锁
基础知识 线程切换代价 Java的线程是映射到操作系统的原生线程之上的,如果阻塞或唤醒一个线程就需要操作系统介入,需要在用户态和内核态之间切换,该切换会消耗大量的系统资源,因为用户态和内核态均有各自专 ...
- java线程 锁_Java多线程(二) 多线程的锁机制
当两条线程同时访问一个类的时候,可能会带来一些问题.并发线程重入可能会带来内存泄漏.程序不可控等等.不管是线程间的通讯还是线程共享数据都需要使用Java的锁机制控制并发代码产生的问题.本篇总结主要著名 ...
- 关于锁机制:数据库锁
一.什么是锁机制?数据库为什么要会有锁机制 数据库是一个多用户使用的共享资源.当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确 ...
最新文章
- APS:大型多模态室内摄像机定位系统
- Singleton Pattern
- [WebGL入门]十二,模型数据和顶点属性
- 蚂蚁前端的开局十年:一切都在路上
- 开发直播APP软件一定要了解的H.264编码,即时通讯中的战斗机
- kafka 0.9 java开发_kafka 0.9 java producer and consumer demo
- (又有惊喜)Redis5.0重量级特性Stream尝鲜
- Java是如何实现跨平台运行的
- 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-1.数据信息安全--微信授权一键登录功能介绍...
- 【优化算法】非洲秃鹫优化算法(AVOA)【含Matlab源码 1805期】
- 考研高等数学第一讲手写笔记 函数、极限与连续
- iTween介绍和用法
- Ubuntu18.04 U盘安装和分区方案
- Win7 安装.Net 4.7.2 失败
- Word 软回车和硬回车
- 【Nodejs】用http模块写一个简单的web服务器
- 中医药大学计算机考试题,浙江中医药大学2013年级研究生《计算机应用》期末考试复习题...
- linux 安装字体库
- wps删除分节符导致前面格式变乱的解决方案
- HTML5 实现扫描识别二维码 生成二维码
热门文章
- javascript对于DOM加强
- 使用微软的TFS云服务来管理小型项目
- 2BizBox-ERP那点事儿系列之4
- 分别是什么意思_美国FBA头程:空派/海派分别是什么意思?
- python把dict转为dataframe,将python OrderedDict转换为datafram
- java 全局变量 内存不回收_JAVA知识梳理:内存管理与垃圾回收机制
- redis 后台运行_第一章 1.3Linux下安装Redis
- python如何通过以太网发送指令_用scapy在python中编写一个以太网桥
- mysql对库授权alter_mysql 数据库授权(给某个用户授权某个数据库)
- plsql登录时显示无服务器,plsql登录提示ORA-12514:TNS:listener does not currently know of service…………...