锁大概有以下名词:

自旋锁,自旋锁的其他种类,阻塞锁,可重入锁,读写锁,互斥锁,悲观锁,乐观锁,公平锁,偏向锁,对象锁,线程锁,锁粗化,锁消除,轻量级锁,重量级锁,信号量,独享锁,共享锁,分段锁

我们所说的锁的分类其实应该按照锁的特性和设计来划分

概述

其实从并发的角度来讲,按照线程安全的三种策略看,主要内容都集中在互斥同步里,我们所讨论的锁也集中在这个部分。这个部分的锁都是悲观锁,第二个部分是非阻塞同步,这个部分也就一种通过CAS进行原子类操作,这个部分可以看成乐观锁,其实也就是不加锁。第三个部分是无同步方案,包括可重入代码和线程本地存储(具体的可以查阅相关博客资料,也可以看这篇)。

我们主要讨论互斥同步。

常见的锁

Synchronized和Lock

其实我们真正用到的锁也就那么两三种,只不过依据设计方案和性质对其进行了大量的划分。

以下一个锁是原生语义上的实现:

Synchronized,它就是一个:非公平,悲观,独享,互斥,可重入的重量级锁

以下两个锁都在JUC包下,是API层面上的实现:

ReentrantLock,它是一个:默认非公平但可实现公平的,悲观,独享,互斥,可重入,重量级锁。

ReentrantReadWriteLocK,它是一个,默认非公平但可实现公平的,悲观,写独享,读共享,读写,可重入,重量级锁。

按照其性质分类

公平锁/非公平锁

公平锁是指多个线程按照申请锁的顺序来获取锁。非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获得锁。有可能会造成优先级反转或者饥饿现象。对于Java ReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。对于Synchronized而言,也是一种非公平锁。由于其并不像ReentrantLock是通过AQS的来实现线程调度,所以并没有任何办法使其变成公平锁。

乐观锁/悲观锁

乐观锁与悲观锁不是指具体的什么类型的锁,而是指看待并发同步的角度。悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为,不加锁的并发操作一定会出问题。乐观锁则认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,会采用尝试更新,不断重新的方式更新数据。乐观的认为,不加锁的并发操作是没有事情的。从上面的描述我们可以看出,悲观锁适合写操作非常多的场景,乐观锁适合读操作非常多的场景,不加锁会带来大量的性能提升。悲观锁在Java中的使用,就是利用各种锁。乐观锁在Java中的使用,是无锁编程,常常采用的是CAS算法,典型的例子就是原子类,通过CAS自旋实现原子操作的更新。

独享锁/共享锁

独享锁是指该锁一次只能被一个线程所持有。共享锁是指该锁可被多个线程所持有。对于Java ReentrantLock而言,其是独享锁。但是对于Lock的另一个实现类ReentrantReadWriteLock,其读锁是共享锁,其写锁是独享锁。读锁的共享锁可保证并发读是非常高效的,读写,写读 ,写写的过程是互斥的。独享锁与共享锁也是通过AQS来实现的,通过实现不同的方法,来实现独享或者共享。对于Synchronized而言,当然是独享锁。

互斥锁/读写锁

上面讲的独享锁/共享锁就是一种广义的说法,互斥锁/读写锁就是具体的实现。互斥锁在Java中的具体实现就是ReentrantLock,读写锁在Java中的具体实现就是ReentrantReadWriteLock

可重入锁

可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。说的有点抽象,下面会有一个代码的示例。对于Java ReentrantLock而言, 他的名字就可以看出是一个可重入锁,其名字是Reentrant Lock重新进入锁。对于Synchronized而言,也是一个可重入锁。可重入锁的一个好处是可一定程度避免死锁。

public sychrnozied void test() {

xxxxxx;

test2();

}

public sychronized void test2() {

yyyyy;

}

在上面代码中,执行test()方法需要获得当前对象作为监视器的对象锁,但方法中又调用了test2的同步方法。

如果锁具有可重入性的话,那么该线程在调用test2时并不需要再次获得当前对象的锁,可以之家进入test2方法进行操作

如果锁不具有可重入性的话,那么该线程在调用test2前会等待当前对象锁的释放,实际上该对象锁已经被当前线程所持有,不可能再次获得,会产生死锁。

按照设计方案来分类

自旋锁/自适应锁

如果物理机器有一个以上的处理器,能让两个或以上的线程同时并行执行,我们就可以让后面请求锁的那个线程“稍等一下”,但不放弃处理器的执行时间,看看持有锁的线程是否很快就会释放锁。为了让线程等待,我们只需让线程执行一个忙循环(自旋),这项技术就是所谓的自旋锁。优点是:自旋等待本身可以避免线程切换的开销。缺点是:自旋等待不能代替阻塞,且先不说对处理器数量的要求,自旋等待本身虽然避免了线程切换的开销,但它是要占用处理器时间的

自适应意味着自旋的时间不再固定了,而是由前 一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。

如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也很有可能再次成功,进而它将允许自旋等待持续相对更长时间,比如100个循环。

如果对于某个锁,自旋很少成功获得过,那在以后要获取这个锁时将可能省略掉自旋过程,以避免浪费处理器资源

这三种锁是指锁的状态。并且是针对Synchronized。在Java 5通过引入锁升级的机制来实现高效Synchronized。这三种锁的状态是通过对象监视器在对象头中的字段来表明的。

偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。

轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。

重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。

分段锁

分段锁其实是一种锁的设计,并不是具体的一种锁,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。我们以ConcurrentHashMap来说一下分段锁的含义以及设计思想,ConcurrentHashMap中的分段锁称为Segment,它即类似于HashMap(JDK7与JDK8中HashMap的实现)的结构,即内部拥有一个Entry数组,数组中的每个元素又是一个链表;同时又是一个ReentrantLock(Segment继承了ReentrantLock)。

当需要put元素的时候,并不是对整个hashmap进行加锁,而是先通过hashcode来知道他要放在那一个分段中,然后对这个分段进行加锁,所以当多线程put的时候,只要不是放在一个分段中,就实现了真正的并行的插入。

但是,在统计size的时候,可就是获取hashmap全局信息的时候,就需要获取所有的分段锁才能统计。分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。

参考资料

锁分类 java_java锁的种类相关推荐

  1. Java 中的锁分类以及锁的原理

    锁分类与原理 锁的分类 锁的分类及基本概念 Java对象在内存中的布局: 锁的升级过程: 锁的本质: synchronized 与Lock 的区别: 互斥锁的原理: 1.读写锁 2.读写锁的原理 3. ...

  2. CC00155.bigdatajava——|JavaMySQL.高级.V27|——|MySQL.v28|锁分类|

    一.MySQL的锁分类 ### --- mysql锁分类--> MySQL数据库由于其自身架构的特点,存在多种数据存储引擎, --> MySQL中不同的存储引擎支持不同的锁机制. --&g ...

  3. 【Java 并发编程】线程锁机制 ( 线程安全 | 锁机制 | 类锁 | 对象锁 | 轻量级锁 | 重量级锁 )

    文章目录 一.线程安全 二.锁机制 ( 类锁 | 对象锁 ) 三.锁分类 ( 轻量级锁 | 重量级锁 ) 一.线程安全 多个线程同时访问 同一个共享变量 时 , 只要能保证 数据一致性 , 那么该变量 ...

  4. 并发控制--悲观锁和乐观锁详解

    背景 考虑下面两个并发带来的问题: 1.丢失更新:一个事务的更新结果覆盖了其它事务的更新结果,即所谓的更新丢失. 2.脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取. 例如: 两个用户同 ...

  5. java分类锁_【基本功】java锁分类详解

    [基础课]--[锁]--锁分类​mp.weixin.qq.com 前言 Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率.本文旨在对锁相关源码(本文中的源码来自J ...

  6. java锁的有哪些_「并发编程」Java锁分类和特点有哪些

    公平锁.非公平锁:公平锁指多个线程按照申请锁的顺序来获取锁,非公平锁就是没有顺序完全随机,所以能会造成优先级反转或者饥饿现象:synchronized 就是非公平锁,ReentrantLock(使用 ...

  7. 多线程高并发 底层锁机制与优化的最佳实践——各种锁的分类 || synchronized 关键字 倒底锁的是什么东西?|| CAS与ABA问题||锁优化||轻量级锁一定比重量级锁的性能高吗

    多线程高并发 底层锁机制与优化的最佳实践 各种锁的分类 加上synchronized 关键字,共享资源就不会出错 synchronized 关键字 倒底锁的是什么东西? synchronized 锁的 ...

  8. 【线程、锁】什么是AQS(锁分类:自旋锁、共享锁、独占锁、读写锁)

    文章目录 1. 什么是AQS 1.1 锁分类 1.2 具体实现 2. AQS底层使用了模板方法模式 3. AQS的简单应用 参考 1. 什么是AQS AQS:全称为AbstractQuenedSync ...

  9. 超屌的多线程锁分类,了解一下?

    推荐阅读: 我总结了72份面试题,累计3170页,斩获了30+互联网公司offer(含BATJM) 2020首战告捷,这份Java面试神技Plus版,让我成功拿到了阿里.京东.字节跳动等大厂offer ...

最新文章

  1. 就在几天前,听说用了 YYYY-MM-dd 的程序员,都在加班改 Bug !
  2. 压缩base 64字符串_ftp下载多个文件,ftp下载多个文件打包成一个压缩包
  3. 【深度学习】谷歌最新提出无需卷积、注意力 ,纯MLP构成的视觉架构!网友:MLP is All You Need ?...
  4. PHP——获取当前日期时间错误解决方案(PHP当前时区设置)
  5. 分布式系统的面试题5
  6. 关于mydumper的.metadata文件丢失
  7. arm linux ping 通百度,linux ---之与ARM开发板相互ping 通
  8. 【三维深度学习】多视角立体视觉模型R-MVSNet
  9. 【摘抄】其实我是间谍!
  10. hadoop的同类技术_Hadoop和Spark的区别是什么?现在都流行用哪种技术?
  11. 制作chrome插件教程
  12. 【数据结构--二叉树】--附超详细图解
  13. 2022-03微软漏洞通告
  14. 计算机添加定时启动软件,有什么软件可以让电脑定时开机?除了设定BIOS!
  15. 汇编语言-王爽 第7章 更灵活的定位内存地址的方法-笔记
  16. 微生物学期末复习重点
  17. 深度学习的时间序列分类
  18. 教师资格证上传照片显示服务器错误,教师资格证报名照片传不上去怎么办,照片有哪些要求—中小学教师资格网...
  19. 从儿时的科幻电影到spaceX的火箭回收
  20. I/O error reading PNG header! java截取png图片时遇到的问题

热门文章

  1. 【饥荒mod制作吧第六篇】发帖小尾巴教程
  2. ubuntu16.04 下 android 4.4.4 源码下载
  3. vim的退出进入及其相应的操作命令
  4. 股市基础知识、股票的种类
  5. TP6 当前访问路由未定义或不匹配
  6. 计算两个有序数组的中位数
  7. 图片和图形之OpenGL ES(8)
  8. PHP排序算法之选择排序
  9. 华为弹性云服务器ECS,自动调整搭配安全保障,畅享硬核存算能力
  10. web前端开发第二阶段——鼠标移入移出事件