【Java线程安全】锁
Java都有哪些锁?
synchronized 和 reentranlock是最常见的,其中前者又JVM提供实现,后者有专门对应的java.util.concurrent包提供;同时后者功能更加丰富、灵活
悲观锁和乐观锁
悲观锁认为,每一次走进同步代码都可能发生线程安全问题,因此只要触及代码块都会加锁,而乐观锁则认为大部分情况都不会出现线程安全问题,所以只要出现问题的时候再自旋CAS
可重入锁和不可重入锁
不可重入锁,就是某线程获取该锁但未释放的时候,如果再次获取该锁,则只能等待;而可重入锁不需要等待,只需要为锁数量加1;其中注意,synchronized和reentrantlock都是可重入锁
Synchronized
对象头信息:存储对象年龄,Class实例地址等
监视器信息:EntrySet和WaitSet,前者是Block状态的线程队列,后者是Wait状态的线程队列
JVM实现的锁,实现原理是利用操作系统的内核态的Mutex互斥量实现的,因为涉及内核态的调用所以一般认为是重量级锁,但后面已经被官方优化过,所以很难说synchronized就效率很低,优化的主要思想还是乐观锁,优化方案有:适应性自旋锁、锁消除、锁粗化、轻量级锁、偏向锁
【自旋锁】自旋锁(Spin Lock),在一个线程进入synchronized代码块,获取锁的时候不直接进入ContetionList(之前已经有线程)等候,而是先自旋等待一下,期待Owner线程马上释放锁;这样虽然对ContetionList里面的线程不太公平但是总体效率能提高;因为线程进入ContetionList阻塞,需要进入内核调度状态,非常耗时;
【轻量级锁】如果大部分情况都是一个线程在使用资源,那么轻量级锁就很有用,轻量级锁就是为了在无多线程竞争的环境中使用CAS来代替mutex,一旦发生竞争,两条以上线程争用一个锁就会膨胀,在CAS成功的线程获取锁,而失败的线程则自旋状态,如果自旋成功那么还是偏向锁状态,否则升级为重量级锁。
【偏向锁】(Biased Lock),偏向锁是在第一个获取后,后面的所有重入都不做同步操作,比轻量级锁还轻,因为它取消了同步原语的操作,也就是轻量级锁的CAS操作也不做了,如果发生竞争的时候,会又其他线程来阻塞偏向线程,然后升级为轻量级锁。
【锁粗化】分析代码,然后合并所有锁的获取和进入微一个锁的获取和进入
【锁消除】根据逃逸技术分析代码,如果线程安全,就取消锁。
要知道,sync是基于对象头的监视器的,所以结合对象头的知识,自旋锁,偏向锁工作如下:
每一个线程在准备获取共享资源时:
第一步,检查MarkWord里面是不是放的自己的ThreadId ,如果是,表示当前线程是处于 “偏向锁”
第二步,如果MarkWord不是自己的ThreadId,锁升级,这时候,用CAS来执行切换,新的线程根据MarkWord里面现有的ThreadId,通知之前线程暂停,
之前线程将Markword的内容置为空。
第三步,两个线程都把对象的HashCode复制到自己新建的用于存储锁的记录空间,接着开始通过CAS操作,
把共享对象的MarKword的内容修改为自己新建的记录空间的地址的方式竞争MarkWord,
第四步,第三步中成功执行CAS的获得资源,失败的则进入自旋
第五步,自旋的线程在自旋过程中,成功获得资源(即之前获的资源的线程执行完成并释放了共享资源),则整个状态依然处于 轻量级锁的状态,如果自旋失败
第六步,进入重量级锁的状态,这个时候,自旋的线程进行阻塞,等待之前线程执行完成并唤醒自己
性能差:为什么synchronize性能差呢,因为该锁利用操作系统的互斥实现,所以会切换内核态和用户态,这过程的开销极大;而线程的阻塞消耗一般,所以Reentrantlock一直在用户态消耗不大。
Renentrantlock
J.U.C提供的锁,实现方式是利用volatile和cas自旋的方式实现,主要核心组件是AQS,该知识点请参见我的另一篇参见AQS的文章
【Java线程安全】锁的更多相关文章
- Java线程:锁
一.锁的原理 Java中每个对象都有一个内置锁,当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行的代码类的当前实例(this实例)有关的锁.获得一个对象的锁也称为获取锁.锁 ...
- Java 线程与锁
Synchronization synchronized语法可以获取锁, 当其他线程持有锁的时候该线程想要获取锁将会进入等待状态, 直到没有其他线程持有该锁 显示使用 synchronized (lo ...
- Java线程与锁
概要:线程的实现方法. 线程调度.线程状态及转换.线程安全(5种分类.3种实现方法.锁优化技术) 进程是OS进行资源分配的基本单位,线程是CPU调度的基本单位. 1.线程的实现方法 可参阅 我是一个进 ...
- java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)
一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...
- java线程 公平锁 ReentrantLock(boolean fair)
一.公平锁 1.为什么有公平锁 CPU在调度线程的时候是在等待队列里随机挑选一个线程,由于这种随机性所以是无法保证线程先到先得的(synchronized控制的锁就是这种非公平锁).但这样就会产生饥饿 ...
- 【Java线程】锁机制:synchronized、Lock、Condition
http://www.infoq.com/cn/articles/java-memory-model-5 深入理解Java内存模型(五)——锁 http://www.ibm.com/develope ...
- Java线程同步锁
把synchronized当作函数修饰符时,示例代码如下: Public synchronized void method(){ //-. } 这也就是同步方法,那这时synchronized锁定的是 ...
- 【java线程】锁机制
转载于:https://blog.csdn.net/vking_wang/article/details/9952063 http://www.infoq.com/cn/articles/java-m ...
- 【Java线程】锁机制:synchronized、Lock、Condition(转)
原文地址 1.synchronized 把代码块声明为 synchronized,有两个重要后果,通常是指该代码具有 原子性(atomicity)和 可见性(visibility). 1.1 原子性 ...
- Java线程八锁
package com.atguigu.juc1205; import java.util.concurrent.TimeUnit; class Phone//Phone.java ---> P ...
随机推荐
- cd4与cd8比值的意义
正常情况下CD4/CD8比值介于1.5—2.5之间,如CD4是每微升血750个,CD8是每微升血460个,这样两者的比值就是1.63. 虽然95%的正常人CD4/CD8的比值都在1以上,但是也有一些正 ...
- 2-08. 用扑克牌计算24点(25) (ZJU_PAT 数学 枚举)
题目链接:http://pat.zju.edu.cn/contests/ds/2-08 一副扑克牌的每张牌表示一个数(J.Q.K分别表示11.12.13,两个司令都表示6).任取4张牌.即得到4个1~ ...
- PL/SQL学习笔记之包
一:包 包是由一组相关的函数,过程,变量,游标等PL/SQL程序设计元素的组合而成的一个PL/SQL程序单元,相当于Java中的类. 包的主要作用是封装:把相同或相似的东西归类,方便维护和管理,提高开 ...
- 每天一个linux命令(16):which
1.命令简介 which (which) 命令的作用是在PATH变量指定的路径中搜索某个系统命令的位置并且返回第一个搜索结果.也就是说使用which命令就可以看到某个系统命令是否存在以及执行的到底是哪 ...
- spring拦截器中使用spring的自动注入
需要在spring的拦截器中使用自定义的服务,这要就设计到将服务注入到拦截器中.网上看的情况有两种: 1. @Configuration public class OptPermissionHandl ...
- SQL Server does not purge row versioning records even the transaction are committed if there are other open transaction running in the databases with read-committed snapshot enabled .
This is a by-design behavior. There is only one allocation unit in tempdb that istracking the versio ...
- 怎么让self.view的Y从navigationBar下面开始计算
原文地址 http://blog.sina.com.cn/s/blog_1410870560102wu9a.html 在iOS 7中,苹果引入了一个新的属性,叫做[UIViewController s ...
- shell md5sum
md5sum out.a echo "fd_limit=$(ulimit -n), fd_used=$(ll /proc/4741/fd | wc -l)" 需找句柄,及fd ...
- 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)
一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...
- swiper4自动轮播切换手动触碰后停止踩坑——属性disableOnInteraction
swiper4轮播设置autoplay自动切换后,即默认设置: <script> var mySwiper = new Swiper('.swiper-container', { auto ...