Java锁的几种应用
Java锁有如下概念:
volatile
synchronized
ReentrantLock
在Java理论与实践系列中对此有过介绍分析:
正确使用 Volatile 变量
JDK 5.0 中更灵活、更具可伸缩性的锁定机制
在此对其中的概念再做一些深入的分析与解释:
1. volatile
提到volatile,很多地方都提及到的是volatile只能保证“可见性”无法保证“原子性”,首先的问题就是什么是可见性,为什么会存在可见性问题。其次通过几个例子说明一下可见性和原子性的区别。
可见性问题主要指一个线程修改了共享变量值,而另一个线程却看不到。引起可见性问题的主要原因是每个线程拥有自己的一个高速缓存区——线程工作内存。深入的原理分析可以参考如下两篇文章:
深入分析Volatile的实现原理
volatile的使用及其原理
通过如下代码可以验证一下volatile不能保证原子性:
public class VolatileTest {public static void main(String[] args) {int count = 1000;Test test = new Test();for (int i = 0; i < count; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}test.increment();}}).start();}try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("count is " + test.getCount());}private static class Test {private volatile int count = 0;void increment() {count++;}int getCount() {return count;}}
}
如果volatile能够保证原子性的话,输出结果应该是1000,但实际上输出结果不确定,可能是992,982。
2. synchronized
还是上面的例子,略作改动,去掉volatile, increment方法定义为synchronized,则可以保证操作原子性,每次输出结果都是1000。
private static class Test {private int count = 0;synchronized void increment() {count++;}int getCount() {return count;}}
关键字有如下用法修饰的对象有如下几种:
修饰一个代码块
public void run() {synchronized(this) {// code block here}
}
private Object lock;
public void run() {synchronized(lock) {// code block here}
}
修饰一个方法
public synchronized void run() {// code block here
}
修饰一个静态方法
public synchronized static void run() {// code block here
}
修饰一个类
public class Test {public void run() {synchronized(Test.class) {// code block here}}
}
synchronized的本质是获取对象锁,因此关键有两点:
锁定的对象,锁定的范围
针对上述几种情况:
修饰一个代码块:锁定的对象是synchronized(xxx)所指定的xxx对象,锁定的范围是{}所包含的代码块
修饰一个方法:锁定的对象是调用该方法的类实例,锁定的范围是该方法
修饰一个静态方法:锁定的对象是该类,即xxx.class对象,锁定的范围是该方法
修饰一个类:实际上是修饰代码块的特例,对象是某个类,即xxx.class
3. ReentrantLock
synchronized 关键字的特点是编码简单,不需要考虑加锁/释放的问题,缺点是不能应对复杂的应用场景,效率不高。为此Java提供了ReentrantLock类,详细介绍分析可以参考:
JDK 5.0 中更灵活、更具可伸缩性的锁定机制
4. 其他
此外还有一些比较有用的包装可以供我们选择,不需要重新造轮子:
BlockingQueue:适用于典型的生产者/消费者模式
Java锁的几种应用相关推荐
- java 中lock,java中lock获取锁的四种方法
在java接口中会存放着许多方法,方便线程使用时的直接调用.对于lock接口大家都不陌生,我们已经初步对概念进行了理解.那么在获取锁的方法上想必还不是很清楚.下面我们就lock获取锁的四种方法分别进行 ...
- 24张图带你彻底理解Java中的21种锁
本篇主要内容如下: 本篇主要内容 本篇文章已收纳到我的Java在线文档. Github 我的SpringCloud实战项目持续更新中 帮你总结好的锁: 序号 锁名称 应用 1 乐观锁 CAS 2 悲观 ...
- 【Java 并发编程】线程锁机制 ( 锁的四种状态 | 无锁状态 | 偏向锁 | 轻量级锁 | 重量级锁 | 锁竞争 | 锁升级 )
文章目录 一.悲观锁示例 ( ReentrantLock ) 二.重量级锁弊端 三.锁的四种状态 ( 无锁状态 | 偏向锁 | 轻量级锁 | 重量级锁 ) 四.锁的四种状态之间的转换 ( 无锁状态 - ...
- 对象头、锁的四种状态、Java和处理器实现原子操作的方式(CAS、锁机制;总线锁定、缓存锁定)
1.对象头 Java对象头里的Mark Word里默认存储对象的HashCode.分代年龄和锁标记位. 32位JVM的Mark Word的默认存储结构如下图所示: 在运行期间,Mark Word里存储 ...
- java中怎么判断一段代码时线程安全还是非线程安全_24张图带你彻底理解Java中的21种锁...
(给ImportNew加星标,提高Java技能) 转自:悟空聊架 本篇主要内容如下: 本篇文章已收纳到我的 Java 在线文档. Github.我的 SpringCloud 实战项目持续更新中. 帮你 ...
- 多图带你彻底理解Java中的21种锁!
作者 | 悟空聊架构 来源 | 悟空聊架构(ID:PassJava666) 本篇主要内容如下: 本篇主要内容 本篇文章已收纳到我的Java在线文档. Github 我的SpringCloud实战项目持 ...
- Java并发 乐观锁和悲观锁 乐观锁的一种实现方式CAS
为什么80%的码农都做不了架构师?>>> 首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人 ...
- Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
Java并发问题–乐观锁与悲观锁以及乐观锁的一种实现方式-CAS </h1><div class="clear"></div><div c ...
- Java实现分布式锁的三种方式
文章目录 前言 一.基于数据库实现分布式锁 二.Redisson实现分布式锁 三.Zookeeper实现分布式锁 四.总结 前言 目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问 ...
最新文章
- 按esc键退出的一个函数
- Redis 缓存使用技巧和设计方案
- jQuery validation插件的使用(转)
- Redox随笔(2)-用Rust语言编写的类UNIX操作系统
- debian及ubuntu挂载本地硬盘的ISO镜像文件
- aspnetcore源码学习(一)
- “约见”面试官系列之常见面试题第十八篇之深拷贝和浅拷贝得区别(建议收藏)
- Django2.0 path 正则匹配不出url的解决方法
- 并发编程游玩---ExecutorService的isShutdown()和isTerminated(),以及一些方法的区别
- 中国移动计算机类行测题目,中国移动笔试题:行测巧用十字交叉法解题
- python天眼查 的融资_python怎么爬取天眼查工商基本信息?
- 优秀的程序员真的不写注释吗?
- 利用python打开摄像头及颜色检测
- EAUML日拱一卒--序列图(Sequence Diagram)::交互和交互使用
- PHP实现图片合并功能(根据群用户头像生成群logo图片)
- 《编程之美》笔记之——24点游戏
- elipse如何退出调试模式
- 2075 Problem G	点菜问题
- NFT带给我们普通人的机遇是什么?
- 解决:‘vue-cli-service‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件