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锁的几种应用相关推荐

  1. java 中lock,java中lock获取锁的四种方法

    在java接口中会存放着许多方法,方便线程使用时的直接调用.对于lock接口大家都不陌生,我们已经初步对概念进行了理解.那么在获取锁的方法上想必还不是很清楚.下面我们就lock获取锁的四种方法分别进行 ...

  2. 24张图带你彻底理解Java中的21种锁

    本篇主要内容如下: 本篇主要内容 本篇文章已收纳到我的Java在线文档. Github 我的SpringCloud实战项目持续更新中 帮你总结好的锁: 序号 锁名称 应用 1 乐观锁 CAS 2 悲观 ...

  3. 【Java 并发编程】线程锁机制 ( 锁的四种状态 | 无锁状态 | 偏向锁 | 轻量级锁 | 重量级锁 | 锁竞争 | 锁升级 )

    文章目录 一.悲观锁示例 ( ReentrantLock ) 二.重量级锁弊端 三.锁的四种状态 ( 无锁状态 | 偏向锁 | 轻量级锁 | 重量级锁 ) 四.锁的四种状态之间的转换 ( 无锁状态 - ...

  4. 对象头、锁的四种状态、Java和处理器实现原子操作的方式(CAS、锁机制;总线锁定、缓存锁定)

    1.对象头 Java对象头里的Mark Word里默认存储对象的HashCode.分代年龄和锁标记位. 32位JVM的Mark Word的默认存储结构如下图所示: 在运行期间,Mark Word里存储 ...

  5. java中怎么判断一段代码时线程安全还是非线程安全_24张图带你彻底理解Java中的21种锁...

    (给ImportNew加星标,提高Java技能) 转自:悟空聊架 本篇主要内容如下: 本篇文章已收纳到我的 Java 在线文档. Github.我的 SpringCloud 实战项目持续更新中. 帮你 ...

  6. 多图带你彻底理解Java中的21种锁!

    作者 | 悟空聊架构 来源 | 悟空聊架构(ID:PassJava666) 本篇主要内容如下: 本篇主要内容 本篇文章已收纳到我的Java在线文档. Github 我的SpringCloud实战项目持 ...

  7. Java并发 乐观锁和悲观锁 乐观锁的一种实现方式CAS

    为什么80%的码农都做不了架构师?>>>    首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人 ...

  8. Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS

    Java并发问题–乐观锁与悲观锁以及乐观锁的一种实现方式-CAS </h1><div class="clear"></div><div c ...

  9. Java实现分布式锁的三种方式

    文章目录 前言 一.基于数据库实现分布式锁 二.Redisson实现分布式锁 三.Zookeeper实现分布式锁 四.总结 前言 目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问 ...

最新文章

  1. 按esc键退出的一个函数
  2. Redis 缓存使用技巧和设计方案
  3. jQuery validation插件的使用(转)
  4. Redox随笔(2)-用Rust语言编写的类UNIX操作系统
  5. debian及ubuntu挂载本地硬盘的ISO镜像文件
  6. aspnetcore源码学习(一)
  7. “约见”面试官系列之常见面试题第十八篇之深拷贝和浅拷贝得区别(建议收藏)
  8. Django2.0 path 正则匹配不出url的解决方法
  9. 并发编程游玩---ExecutorService的isShutdown()和isTerminated(),以及一些方法的区别
  10. 中国移动计算机类行测题目,中国移动笔试题:行测巧用十字交叉法解题
  11. python天眼查 的融资_python怎么爬取天眼查工商基本信息?
  12. 优秀的程序员真的不写注释吗?
  13. 利用python打开摄像头及颜色检测
  14. EAUML日拱一卒--序列图(Sequence Diagram)::交互和交互使用
  15. PHP实现图片合并功能(根据群用户头像生成群logo图片)
  16. 《编程之美》笔记之——24点游戏
  17. elipse如何退出调试模式
  18. 2075 Problem G 点菜问题
  19. NFT带给我们普通人的机遇是什么?
  20. 解决:‘vue-cli-service‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件

热门文章

  1. Solidity智能合约开发(提高篇)
  2. 华硕主板如何用u盘启动计算机,华硕主板u盘启动按f几_华硕主板怎么设置u盘启动-硬件之家...
  3. VB6与SQLServer数据库连接实例ADO
  4. matlab的汉明窗函数如何导出,C中的汉宁和汉明窗口函数#
  5. windows下的命令行工具babun
  6. 人工智能就是更高级的、直接产生价值的智能
  7. 最新!超10多所高校明确不再为全部研究生提供宿舍!
  8. RuoYi-App移动版(uni-app)微信公众号授权登录
  9. 面试部分梳理 - JVM
  10. 昆大丽经典线路~云南游第一趴