一、锁的作用和比较

1、Lock接口及其类图

Lock接口:是Java提供的用来控制多个线程访问共享资源的方式

ReentrantLock:Lock的实现类,提供了可重入的加锁语义

ReadWriteLock:读写锁的接口

ReentrantReadWriteLock: ReadWriteLock的实现类,维护一对锁,一个读锁(ReentrantReadWriteLock.ReadLock)和一个写锁(ReentrantReadWriteLock.writeLock),实现了锁的分离,提高了性能和吞吐量。也提供了可重入的加锁语义

ReentrantReadWriteLock.ReadLock:

ReentrantReadWriteLock.WriteLock:

Condition:条件队列接口,提供类似于Object监视器方法 ,可与Lock实现等待/通知模式

AbstractQueuedSynchronizer.ConditionObject: Condition的实现类

AbstractQueuedLongSynchronizer.ConditionObject:Condition的实现类

AbstractOwnableSynchronizer:可以被线程专有的同步器

AbstractQueuedSynchronizer(AQS):继承于AbstractOwnableSynchronizer,Java中构建锁和其他同步器的基础构建

AbstractQueuedLongSynchronizer:AbstractQueuedSynchronizer的一个版本,实现对Long型同步状态的同步。

(1)Lock与Synchronized同步锁、内置锁的的区别

加锁机制

特性

优点

缺点

适用范围

Synchronize(内置锁 1、实现操作的互斥性和原子性
2、实现内存的可见性
3、禁止重排序
4、锁的获取和释放都是隐式的
5、每一个对象都是一个内置锁
6、必须在获取锁的代码块内释放,简化编码工作
7、锁的获取与释放都是基于代码块的(获取锁的操作和释放锁的操作在同一个代码块)

1、JVM的内置属性(当 JVM 用 synchronized 管理锁定请求和释放时,JVM 在生成线程转储时能够包括锁定信息。这些对调试非常有价值,因为它们能标识死锁或者其他异常行为的来源。 Lock 类只是普通的类,JVM 不知道具体哪个线程拥有 Lock 对象。)

2、可重入

3、无需实现锁的获取和释放

1、尝试获取已被独占的锁时线程会被阻塞
2、独占排他式锁,互斥锁,每次只能有一个线程持有该锁
3、无法实现非阻塞的加锁模式

4、无法中断一个正在等候获得锁的线程,也无法通过轮询得到锁,如果不想等下去,也就没法得到锁。

5、同步还要求锁的释放只能在与获得锁所在的堆栈帧相同的堆栈帧中进行,多数情况下,这没问题(而且与异常处理交互得很好),但是,确实存在一些非块结构的锁定更合适的情况

优先使用
2、监视器方法( wait(),waite(timeout),notify(),notifyAll() )与Synchronize实现通知/等待模式

ReentrantLock

1、实现操作的原子性和互斥性
2、实现内存的可见性
3、禁止重排序
5、锁的获取和释放都是显示的
6、提供了可轮询、可定时、可中断的、公平性的锁获取机制
7、实现非块的加锁模式
1、性能优于内置锁
2、可重入
3、可在截止时间前获取锁
4、可非阻塞获取锁(尝试获取已被占用的锁的线程状态变更为等待,而不是阻塞)
5、可实现公平性锁
1、锁的获取和释放必须显示的执行锁的释放操作,不能制动清除锁
2、独占排他式锁,互斥锁,每次只能有一个线程持有该锁
1、需要使用锁的高级功能(可定时,可轮询,可以中断)的时候才使用LOCK
2、与Condition实现等待/通知模式
ReentrantReadWriteLock 1、分离了读锁和写锁,提供了读锁多线程共享访问和写锁独占访问 1、多读少写的情况下性能优于排他锁 在不是多读少写的情况下性能低于排它锁 多读少写

二、Java构建锁的基础组件AQS(探究锁的实现原理)

简介:队列同步器AbstractQueueSynchronizer(AQS)是用来构建锁或者其他同步组件的基础框架,使用一个int成员变量表示同步状态,通过内置FIFO队列来实现资源获取线程的的排队工作。

(AbstractQueuedLongSynchronizer是用Long型来表示同步状态)

使用模式:

通过子类继承AQS并实现它的抽象方法,并作为自定义同步组件的静态内部类,代理实现相关方法。

内置FIFO队列:AbstractQueueSynchronizer.Node表示队列节点,用来保存获取同步状态失败的线程引用、等待状态、前驱后继节点。

获取同步状态失败的节点添加到队列的尾部(通过CAS设置尾节点)

1、AQS独占式同步状态获取和释放的工作原理

独占式获取同步状态的获取失败的时生成的节点类型为Node.EXCLUSIVE(独占式),在加入到同步队列末尾后,进入节点自旋中,只至前驱节点为头结点且成功获取同步状态才可退出。

acqiure()获取锁,release()释放锁

2、AQS共享式同步状态获取和释放的工作原理

共享式获取同步状态时生成节点的类型为Node.SHARED(共享式),但是将节点插入到同步队列末尾的时候并不适用CAS。

tryAcquireShare() 获取同步状态

tryReleaseShared()通过循环和CAS实现线程安全的释放共享式锁。

3、独占式超时获取同步状态的工作原理

doAcquire(arg,nanosTimeout):超时获取同步状态

acquireInterruptibly(arg):可响应中断的获取同步状态

三、重入锁、公平锁、非公平锁

 

含义

优点

缺点

公平锁

锁的获取顺序严格按照锁等待的时间,等待时间越长的最优先获取 减少发生“线程饥饿”的概率 性能开销大(因为线程上下文切换次数多)
非公平锁 锁的获取采用抢占式获取,锁的默认实现 性能开销小(因为进行线程上下文切换的次数少),提供更大的吞吐量 会出现“线程饥饿”问题

四、Condition接口

对比项

Object监视器方法

Condition

前置条件 获取对象的锁 Lock.lock()
Condition condttion=Lock.newCondition()
调用方式 object.wait() condition.wait()
等待队列个数 一个 多个
同步队列 一个 一个
当前线程释放锁并进入等待状态 支持 支持
等待状态不响应中断 支持 支持
超时等待状态 支持 支持
定时等待状态 不支持 支持
唤醒等待队列中的一个线程 支持 支持
唤醒等待队列中的全部线程 支持 支持
响应中断 不支持 支持
实现等待/通知模式 与Synchronize搭配使用 与Lock搭配使用
     

探究Java中的锁的更多相关文章

  1. 初步探究java中程序退出、GC垃圾回收时,socket tcp连接的行为

    初步探究java中程序退出.GC垃圾回收时,socket tcp连接的行为 今天在项目开发中需要用到socket tcp连接相关(作为tcp客户端),在思考中发觉需要理清socket主动.被动关闭时发 ...

  2. 深入介绍Java中的锁[原理、锁优化、CAS、AQS]

    1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...

  3. java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁(转载)

    之前做过一个测试,详情见这篇文章<多线程 +1操作的几种实现方式,及效率对比>,当时对这个测试结果很疑惑,反复执行过多次,发现结果是一样的: 1. 单线程下synchronized效率最高 ...

  4. Java 中的锁

    Java中的锁分类 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分 ...

  5. Java中的锁(转)

    Java中的锁 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂.因为锁(以及其它更高级的线程同步机制)是由synchronized同步 ...

  6. java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁

    之前做过一个测试,详情见这篇文章<多线程 +1操作的几种实现方式,及效率对比>,当时对这个测试结果很疑惑,反复执行过多次,发现结果是一样的: 1. 单线程下synchronized效率最高 ...

  7. 深入理解Java中的锁

    转载:https://www.jianshu.com/p/2eb5ad8da4dc Java中的锁 常见的锁有synchronized.volatile.偏向锁.轻量级锁.重量级锁 1.synchro ...

  8. JAVA 中无锁的线程安全整数 AtomicInteger介绍和使用

    Java 中无锁的线程安全整数 AtomicInteger,一个提供原子操作的Integer的类.在Java语言中,++i和i++操作并不是线程安全的,在使用的时候, 不可避免的会用到synchron ...

  9. Java中的锁[原理、锁优化、CAS、AQS]

    1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...

随机推荐

  1. Atitit 管理的模式扁平化管理 金字塔 直线型管理 垂直管理 水平管理 矩阵式管理 网状式样管理 多头管理 双头管理

    Atitit 管理的模式扁平化管理  金字塔 直线型管理 垂直管理 水平管理 矩阵式管理 网状式样管理 多头管理 双头管理 1.1. 矩阵管理 1 1.2. 相关信息 矩阵的历史 1 1.3. 基于“ ...

  2. Session 在分布式系统中实现方式

    ##server独立Session 例如以下图所看到的: server独立Session要求用户的每次请求都必须在同一台应用server上面操作,这就要求负载均衡server每次都能把用户的请求发送到 ...

  3. SQL Server 2016新特性:数据库级别配置

    新的  ALTER DATABASE SCOPED CONFIGURATION (Transact-SQL) 用来配置数据库级别配置. 这个语句可以配置每个数据库的配置: 清理过程cache 设置MA ...

  4. 【神经网络】Dependency Parsing的两种解决方案

    一.Transition-based的依存解析方法 解析过程:首先设计一系列action, 其就是有方向带类型的边,接着从左向右依次解析句子中的每一个词,解析词的同时通过选择某一个action开始增量 ...

  5. eclipse下安装windowbuilder(一定要看)

    访问页面https://www.eclipse.org/windowbuilder/download.php,查看更新连接 这个是**连接地址**,要复制粘贴到eclipse里. !! 复制地址!!

  6. 微信开发时调用jssdk,在安卓设备中成功调用;在ios设备中返回错误消息:config fail,无其他具体错误消息,且接口权限显示获取ok,无法调用

    js代码如下: JavaScript code   ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ...

  7. LiveSwitch白皮书

    https://www.frozenmountain.com/media/1224/frozen-mountain-software-liveswitch-white-paper.pdf —————— ...

  8. 框架源码系列十二:Mybatis源码之手写Mybatis

    一.需求分析 1.Mybatis是什么? 一个半自动化的orm框架(Object Relation Mapping). 2.Mybatis完成什么工作? 在面向对象编程中,我们操作的都是对象,Myba ...

  9. 基于【CentOS-7+ Ambari 2.7.0 + HDP 3.0】HAWQ数据仓库 使用之 gpfdist协议

    一.HAWQ基本安装自带gpfdist协议 gpfdist是HAWQ支持的外部表访问协议之一,这是hawq自带的一个简单的集成http服务命令. 在我的前述安装hawq之后,gpfdist命令位于ha ...

  10. PXE(preboot execution environment):【网络】预启动执行环节:引导 live光盘 ubuntu livecd 18.04+:成功

    比较艰难的成功了. 艰难在于:吱吱吱吱(知知知知知):就是歌init启动参数而已! 最最艰难在于:这个nfs服务器软件有很大的关系.很多时候不是你不行,而是条件不具备 or 条件看似具备但其实有问题 ...