【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 ...
随机推荐
- iOS链接库的冲突
最近在打包的时候,遇到一个坑.特此记录一下 起因是发现 Unity 5.4 版本,使用c#写的下载,下载速度无法突破 2M/s,同样的网络,后来横向对比使用原来 Cocos2d 开始的游戏,可以达到 ...
- centos7下使用rpm包安装clickhouse
clickhouse是由俄罗斯Yandex公司开发的列式存储数据库,于2016年开源,clickhouse的定位是快速的数据分析,对于处理海量数据的情况性能非常好,在网上也有很多测试的案例,在大数据的 ...
- Hadoop+HBase 集群搭建
Hadoop+HBase 集群搭建 1. 环境准备 说明:本次集群搭建使用系统版本Centos 7.5 ,软件版本 V3.1.1. 1.1 配置说明 本次集群搭建共三台机器,具体说明下: 主机名 IP ...
- shell编程学习笔记(三):Shell中局部变量的使用
现在我们看一下Shell中局部变量的使用 以下蓝色字体部分为Linux命令,红色字体的内容为输出的内容: # cd /opt/scripts # vim script03.sh 开始编写script0 ...
- ES6 与 React
Node和NPM/*安装npm*/npm installnpm install <package>npm install -g <package> /*更新安装包*/npm u ...
- servlet的xx方式传值中文乱码
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOEx ...
- LIN 笔记
LIN 使用了 1 根线来进行通信,但是,它必须要参考 VBat 和 GND.离开这两个参考电平,并没有办法来判断线上的 bit 状态. 另外,根据经典的 LIN 驱动电路(一个 OC 门),RX 接 ...
- Rabbit五种消息队列学习(一) – 总述
RabbitMQ支持五种消息传递类型,分别如下图所示: 上图中显示6中消息队列分别为: 1.简单队列 一个生产者将消息放到队列中,一个消费者监听队列 2.工作队列(Work queues) 一个生产者 ...
- c#异常重试机制
有时候我们碰到程序异常了,想让程序继续重新执行,进行重试,这时候就需要有一个合适的方法来进行操作: 自己写代码控制太麻烦了,也容易出错.这时候当然是站在巨人的肩膀上, https://github.c ...
- Unity应用架构设计(4)——设计可复用的SubView和SubViewModel(Part 2)
在我们设计和开发应用程序时,经常要用到控件.比如开发一个客户端WinForm应用程序时,微软就为我们提供了若干控件,这些控件为我们提供了可被定制的属性和事件.属性可以更改它的外观,比如背景色,标题等, ...