jdk中常见得锁知识有violatile、synchronized、Lock,该系列文章会以锁做为引子,先整体介绍三类锁的特性,然后在分别介绍,其中violatile、synchronized关键字都是java的基础关键字,我会主要从理论方面去介绍。而Lock由于是java中的接口,且有对应的实现类,所以这块我会从理论和源码的两个角度去介绍。
1、什么是锁、锁的作用是什么、锁有哪些种类
实际生活中锁是一种工具,用于控制门户的访问。在java中锁其实类似,主要用于控制对于资源的访问,当我们访问某些特定资源前,先获取锁的信息,然后才能去访问。java开发中我们经常听到看到乐观锁、悲观锁、自旋锁、非自选锁等状态,那么你对这些锁有个完整的概念吗?下面是我整理的一些锁分类,可能有所不全,仅供大家参考:
线程是否被锁住挂起:悲观锁、乐观锁 (自旋、适应性自旋)
线程竞争锁是否有序:公平锁、非公平锁
一个线程能否多次拿锁:可重入锁、非可重入锁
不同线程能否共用一把锁:共享锁、排它锁
synchronized锁优化:无锁、偏向锁、轻量级锁、重量级锁
以上是常用的锁种类,在java锁可能同时具有多个特性,比如synchronized是可重入悲观锁。所以对于锁的概念要灵活的了解,特别是synchronized关键字的优化流程。这里有好几种锁一定要区分开各个锁的使用情景。
2、JMM是什么
锁用于控制访问,所以和多线程的并发安全性有关。那JMM又是什么,它和锁之间的关系是什么呢?
JMM( java memory model ) 又称java内存模型,他不是真实存在的,是和多线程相关的一组“规范”,需要每个 JVM 的实现都要遵守这样的“规范”,有了 JMM 的规范保障,并发程序运行在不同的虚拟机得到出的程序结果才是安全可靠可信赖。要理解java内存模型,先了解几个JMM相关的概念和组成:
工作内存主内存:我们正常开发的时候CPU的处理速度很快,内存的刷新速度与之相比差了很多,如果为了等待内存的刷新而让cpu等待,这比较浪费资源。为了充分发挥CPU功能,JMM把内存分为主内存和工作内存的概念,每条线程处理数据时先去主内存拉数据,处理结束后将新数据再刷新到主内存。这样可以保证资源的充分利用。
happen-before原则:java编写结束运行前有个编译阶段,这个阶段编译器以及后续的处理器可能会重排指令从达到处理速度提升的目的,但是开发人员再开发时却很头疼这种优化,因为程序员不知道优化后代码在访问工作内存和主内存时是否数据安全。为了协调编译器和程序员的开发,相关专家组定义了happens-before原则,它包含八大原则,通过该原则限制了多线程访问的线程安全性。
八大原子操作:JMM定义了read、write、load、store、use、assign、lock、unlock八大原子操作,访问内存时通过这些原子操作保证每一数据相关操作的安全性
内存屏障:内存屏障的本质是一组cpu指令,通过内存屏障可以保证编译器处理器对内存屏障范围内的数据不做指令重拍。
JMM 是一个抽象概念,由于 CPU 多核多级缓存、为了优化代码会发生指令重排的原因,JMM 为了屏蔽细节,定义了一套规范,保证最终的并发安全。它抽象出了工作内存于主内存的概念,并且通过八个原子操作以及内存屏障保证了原子性、内存可见性、防止指令重排
3、JVM是什么、和JMM有啥区别
JVM 内存结构和 Java 虚拟机的运行时区域有关、比如常说的堆、栈、程序计数器、类加载、垃圾回收等概念都和JVM相关
Java 内存模型和 Java 的并发编程有关。
4、violatile、synchronized、Lock如何实现锁的功能、相互的区别是什么
violatile:java关键字,只能实现内存可见性和禁止指令重排,用于修饰变量,在变量层面可以客观认为实现了锁的功能,在方法层面则不具有锁的功能
synchronized:java关键字,具备锁功能,非公平可重入锁,依赖底层操作系统实现锁功能,可修饰变量、方法、方法块,是个重量级锁,jdk1.6优化后具有无锁、偏向锁、轻量级锁、重量级锁的场景切换功能。
Lock:java接口,程序员可以直接操控的锁,根据自定义几乎可以实现所有种类锁的功能,java并发包中大多锁也用到了Lock锁。
5、总结
本文先介绍了锁,以及锁的功能和使用原因,随后介绍了锁出现的基础-JMM概念,最后大致介绍了java中实现锁技术的几种方式,以及区别。后续将针对各个锁技术从理论和源码的角度进行讲解。
实在是文笔不行,对于概念的描述总是心有前言,难汇一句,直接抄别人的成果物更是不好,所以在理论介绍这块我大多从整体上进行介绍,在后续的源码分析阶段则是会详细介绍,并对源码中疑难点做出通俗易懂的解释说明。
该系列文章中用到了一些之前浏览博客和书籍里的知识,当时没有记录各个知识点的出处,如果文章中引用了某位大佬的文章而没有注释,可以直接联系我进行添加。如果贸然引用给你带来不便,敬请谅解,谢谢!
参考链接: