扯扯Java中的锁
前言
又过去了一个周末,最近陆陆续续的看了《并发编程的艺术》一书,对锁有不少感悟,这次就聊聊Java中的锁事。本文纯粹是漫谈,想到哪说到哪,但准确性肯定会保证,倘若有不正确之处,还请交流指正。
正文
作为Java开发, 说到锁第一时间想到的肯定是synchronized和juc包中的lock锁这俩兄弟,但如果眼光放开点,会发现还有很多其他的锁:集群/分布式环境下的分布式锁、mysql中的那一家子锁、操作系统中基于信号量/互斥量等构成的锁。。。上面说的是锁的应用场景,而说起锁本身,定义的类型也不少,什么悲观锁/乐观锁、独占锁/共享锁、读写锁、公平锁/非公平锁、重入锁、轻量级锁/重量级锁、自旋锁、偏向锁...
锁是干什么的?用个人的话来总结一下就是:用于控制不同访问来源对同一数据的访问顺序。也就是说锁的应用涉及到两个关键条件:不同访问来源(可以是不同线程、不同进程、不同APP)和操作同一数据(即共享的数据)。
下面对锁进行一下总结,首先按锁的实现思想分类:
悲观锁和乐观锁属于锁的实现思想,synchronized是悲观锁,而基于乐观锁思想的实现是以CAS为基础构建的lock锁,同样mysql中的锁属于悲观锁,用redis或者zk构建的分布式锁也都是悲观锁,操作系统中基于信号量/互斥量等构建起来的锁也都属于悲观锁范畴。所以用悲观锁/乐观锁的思想标准来看锁,发现各种各样的锁定义其实都在这二者的思想范围内,没有能跑出该范围的。
独占锁/共享锁(读写锁)属于锁的占用类型,有这两种分类的原因就是为了提高系统的并发能力--读不影响读,这里可以再引申一步,mysql为了进一步提高并发能力通过数据多版本使得读跟写也不冲突。其实这里就是提高并发能力的一条线:先是不管读请求还是写请求统统排队进行,后来将读写分开提高读读的效率,再后来通过数据多版本使得读写可以同时进行,后面还能再提高吗?或许参考redis的单线程内存操作是一个方向,但对于复杂数据形式和大数据量却不适合。
公平锁和非公平锁主要针对的是获取锁的方式,公平就是一起排队先排队的先获取到锁,而非公平则表示一起竞争后来的也可能先获取到锁。公平锁的应用场景很少,而且主要是通过lock锁实现的,平时基本都是用非公平锁,无他,非公平锁并发量比公平的强了不止一点。但要额外说一下,lock锁中的非公平模式并不是完全的非公平,如果两次获取不到锁则进入阻塞队列,进入阻塞队列中后,它就只能按队列中的顺序挨个获取锁了,所以lock锁中的非公平模式并不是彻头彻尾的非公平,世间尚存一丝公道。。。
重入锁和非重入锁属于锁的性质,这个很好理解,可以同一获取锁的来源能重复获取的锁就是可重入的,非可重入的场景很少,我们平时接触的基本都是可重入。可重入的实现,基本原理都是在获取到锁之后,将对象记录下来,下次再触发获取锁的操作时先比对一下当前对象与已记录对象是否是同一个,是的话则能获取到锁,锁计数+1。详情可见ReentrantLock的加锁过程。
由于synchronized锁是JVM本身自带的关键字,所以针对synchronized锁做了很多优化,偏向锁/轻量级锁/自旋锁/重量级锁等概念都是来自于此(对synchronized锁等讲解可移步博主之前写过的一/二/三系列【https://i.cnblogs.com/posts?cateId=1466867&page=1】)。其实从原理上来说,自旋锁不是锁,只是在获取不到锁时先自循环一定次数继续尝试获取锁,如果仍然获取不到再阻塞,是针对很快能获取到锁的场景进行的优化处理。
下面再来几张图梳理下思绪:




扯扯Java中的锁的更多相关文章
- 深入介绍Java中的锁[原理、锁优化、CAS、AQS]
1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...
- 探究Java中的锁
一.锁的作用和比较 1.Lock接口及其类图 Lock接口:是Java提供的用来控制多个线程访问共享资源的方式. ReentrantLock:Lock的实现类,提供了可重入的加锁语义 ReadWrit ...
- java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁(转载)
之前做过一个测试,详情见这篇文章<多线程 +1操作的几种实现方式,及效率对比>,当时对这个测试结果很疑惑,反复执行过多次,发现结果是一样的: 1. 单线程下synchronized效率最高 ...
- Java 中的锁
Java中的锁分类 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分 ...
- Java中的锁(转)
Java中的锁 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂.因为锁(以及其它更高级的线程同步机制)是由synchronized同步 ...
- java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁
之前做过一个测试,详情见这篇文章<多线程 +1操作的几种实现方式,及效率对比>,当时对这个测试结果很疑惑,反复执行过多次,发现结果是一样的: 1. 单线程下synchronized效率最高 ...
- 深入理解Java中的锁
转载:https://www.jianshu.com/p/2eb5ad8da4dc Java中的锁 常见的锁有synchronized.volatile.偏向锁.轻量级锁.重量级锁 1.synchro ...
- JAVA 中无锁的线程安全整数 AtomicInteger介绍和使用
Java 中无锁的线程安全整数 AtomicInteger,一个提供原子操作的Integer的类.在Java语言中,++i和i++操作并不是线程安全的,在使用的时候, 不可避免的会用到synchron ...
- Java中的锁[原理、锁优化、CAS、AQS]
1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...
随机推荐
- List<List<Object>> list = new ArrayList<List<Object>>(); 求回答补充问题 list.get(position).add(Object);为什么会报错啊我想在对应的list里面添加对象
public static void main(String[] args){ List<List<Object>> list = new ArrayList<List& ...
- 图解resilience4j容错机制
Resilience4j是一个轻量级.易于使用的容错库,其灵感来自Netflix Hystrix,但专为Java 8和函数式编程设计.轻量级,因为库只使用Vavr,它没有任何其他外部库依赖项.相比之下 ...
- webpack4.X + react搭建
环境准备工作:windows7.webStorm 2017.1.4.Nodejs 8.7.0.npm 5.4.2 PS:安装的时我们都带上版本,这样即便webpack版本发生变化,也不会出现版本问题. ...
- 优雅关闭服务下线(Jetty)
在很多时候 kill -9 pid并不是很友好的方法,那样会将我们正在执行请求给断掉,同时eureka 中服务依旧是处于在线状态,这个时候我们可以使用官方提供的actuator来做优雅的关闭处理 - ...
- web前端开发_文件/目录/样式/函数等命名规范
页面的命名规则 统一用翻译的英文命名(推荐) 统一用拼音命名(拼音的简化也可) 如果文件名过长,企业要提前约定一份缩写的规范,如pro—product 例如: 首页—index 产品列表—prolis ...
- 6.26模拟赛(1)总结(T1:信息传递;T2:传染病控制;T3:排列;T4:最大数)
16:33:56 2020-06-26 当然可以先看一下成绩: 非常显然的成绩不能算有多好,当然其实这也可能是假期水课的报应 (额) 但是比我集训前想象的要好一点(集训时想象的是排名前30就可以,嗯 ...
- P4408 逃学的小孩 题解
题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:"喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?"一听说要考试,Chris的父母就心 ...
- 【Nginx】实现负载均衡、限流、缓存、黑白名单和灰度发布,这是最全的一篇了!
写在前面 在<[高并发]面试官问我如何使用Nginx实现限流,我如此回答轻松拿到了Offer!>一文中,我们主要介绍了如何使用Nginx进行限流,以避免系统被大流量压垮.除此之外,Ngin ...
- Maven 专题(一):Maven 安装与配置(vscode)
0.首先了解一下maven安装目录 Bin:该目录包含Mvn运行的脚本 Boot:Maven自身的类加载器框架 Conf:包含非常重要的文件setting.xml Lib:该目录包含了所有Maven运 ...
- JVM 专题四:类加载子系统(二)双亲委派机制
2. 双亲委派机制 2.1 双亲委派机制工作原理 2.1.1 原理 Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存,生成class对象 ...