前言

Java 中的 synchronized关键字可以在多线程环境下用来作为线程安全的同步锁。本文不讨论 synchronized 的具体使用,而是研究下synchronized底层的锁机制,以及这些锁分别的优缺点。

一 synchronized机制

synchronized关键字是JAVA中常用的同步功能,提供了简单易用的锁功能。
synchronized有三种用法,分别为:

  • 用在普通方法上,能够锁住当前对象。
  • 用在静态方法上,能够锁住类
  • 用在代码块上,锁住的是synchronized()里的对象

在JDK6之前,synchronized使用的是重量级锁制,在之后synchronized加入了锁膨胀机制,显著提升了synchronized关键字的效率。

基于synchronized关键字,我们来了解下几种类别的锁,并且讲解synchronized的锁膨胀机制。

synchronized锁是非公平锁。并且一个被synchronized锁住的对象或类,就是一把锁。

另外一提,所有锁都是存储在Java对象头里的,Java对象头里的Mark Word里默认存储对象的HashCode,分代年龄和锁标记位。也就是说Mark Word记录了锁的状态

二 锁膨胀机制与几类锁

锁膨胀是不可逆的

2.1 偏向锁

synchronized在JDK1.6以后默认开启偏向锁synchronized最初都是偏向锁

表现:一个线程获取锁成功后,会在对象头里记录线程ID,以后该线程获取和释放锁都没有任何花费。(因为该锁已经被绑定在该线程上了,且在膨胀前不会改变),如果其他线程尝试获取这个锁,偏向锁将会膨胀为轻量锁

优点:在只有一个线程使用锁的时候获取和退出锁没有任何花费

缺点:锁竞争激烈会很快升级为轻量锁,那么维持偏向锁的过程就是在浪费计算机资源。(不过因为偏向锁本身就很轻量,因此浪费的资源并不多)

小结:只有一个线程使用锁的情况下,synchronized使用的锁为偏向锁
如果锁竞争激烈,可以通过配置JDK禁用偏向锁

2.2 轻量锁

一把锁不止一个线程使用,则偏向锁膨胀为轻量锁

表现:线程获取轻量锁时,会直接用CAS修改对象头里锁的记录,如果修改失败,代表此时锁存在多个线程的竞争,轻量锁将会膨胀为重量锁

优点:在线程之间使用锁不存在竞争时,一次CAS操作就能获取和退出锁

缺点:与偏向锁类似

小结:只要一把锁不止一个线程获取过,偏向锁就会膨胀为轻量锁

2.3 重量锁

一把锁存在多线程竞争,则轻量锁开始自旋,自旋一定次数后仍没获取锁,则膨胀为重量锁(存在竞争时,轻量锁虽然会先自旋,但是最终往往都会膨胀为重量锁)

表现:线程获取重量锁时,如果获取失败(即锁已被其他线程获取),则使用自适应自旋锁,自旋一定次数后仍没获取锁,则进入阻塞队列等待。

优点:未获取到的锁进入阻塞队列,节约CPU资源。(好吧感觉其实是没有啥优点)

缺点:重量锁是通过对象内部的监视器(monitor)实现,其中monitor的本质是依赖于底层操作系统的Mutex Lock实现,操作系统实现线程之间的切换需要从用户态到内核态的切换,切换成本非常高。

小结:只要一把锁存在多线程竞争,轻量锁就会膨胀为重量锁

自旋锁

synchronized轻量锁重量锁,使用了自适应自旋锁进行性能优化

首先介绍自旋锁

表现:线程获取锁失败后,不会进入阻塞等待,而是再次尝试去获取锁,如此反复,直到获取到锁,或者自旋结束那么会阻塞等待。

解决问题:在某些场景下,线程持有锁的时间非常短。在线程获取锁失败后,如果线程进入阻塞将会带来线程上下文的切换,上下文切换的时间可能反而高于线程反复尝试获取锁的时间。
此时线程原地等待去重复获取锁。反而在性能上更有优势。

缺点:

  1. 单核CPU没有线程并行,反复尝试会导致进程无法继续运行。
  2. 重复尝试导致了CPU的占用,如果CPU资源紧张的话反而会性能下降
  3. 如果锁的竞争时间过长,不仅没有性能提升,还浪费了大量CPU资源。

优化:使用自适应自旋锁。自适应自旋锁会根据之前的锁获取记录,优化调整自旋时间,避免造成不必要的自旋。

三 具体synchronized流程

Java:synchronized关键字引出的多种锁的更多相关文章

  1. Java Synchronized 关键字

    本文内容 Synchronized 关键字 示例 Synchronized 方法 内部锁(Intrinsic Locks)和 Synchronization 参考资料 下载 Demo Synchron ...

  2. Java synchronized 关键字详解

    Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 sync ...

  3. Java synchronized关键字用法(清晰易懂)

    本篇随笔主要介绍 java 中 synchronized 关键字常用法,主要有以下四个方面: 1.实例方法同步 2.静态方法同步 3.实例方法中同步块 4.静态方法中同步块 我觉得在学习synchro ...

  4. java synchronized关键字浅探

    synchronized 是 java 多线程编程中用于使线程之间的操作串行化的关键字.这种措施类似于数据库中使用排他锁实现并发控制,但是有所不同的是,数据库中是对数据对象加锁,而 java 则是对将 ...

  5. java synchronized关键字

    引用其他人的一段话 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchro ...

  6. Java synchronized关键字的理解

    转载自:http://blog.csdn.net/xiao__gui/article/details/8188833 在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环 ...

  7. java synchronized关键字浅析

    synchronized这个关键字想必学Java的人都应该知道. 直接上例子: 方法级别实例 public class AtomicInteger { private int index; publi ...

  8. [java] java synchronized 关键字详解

    Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一 ...

  9. java synchronized关键字的底层实现

    每个对象都有一个锁(Monitor,监视器锁),class对象也有锁,如果synchronized关键字修饰同步代码块,通过反编译可以看到,其实是有个monitorenter和monitorexit指 ...

随机推荐

  1. WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形

    原文:WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形 说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘> ...

  2. mysql重置root密码,并设置可远程访问

    linux系统: mysqld_safe --skip-grant-tables & mysql -u root use mysql UPDATE user SET host = '%' wh ...

  3. WPF 通过CommandBinding捕获命令

    RoutedCommand与业务逻辑无关,业务逻辑是通过CommandBinding来实现 using System; using System.Collections.Generic;using S ...

  4. mysql 视图,存储过程,游标,触发器,用户管理简单应用

    mysql视图——是一个虚拟的表,只包含使用时动态查询的数据 优点:重用sql语句,简化复杂的SQL操作,保护数据,可以给用户看到表的部分字段而不是全部,更改数据格式和表现形式 规则: 名称唯一,必须 ...

  5. Go 的文件系统抽象 Afero

    Afero 是一个文件系统框架,提供一个简单.统一和通用的 API 和任何文件系统进行交互,作为抽象层还提供了界面.类型和方法.Afero 的界面十分简洁,设计简单,舍弃了不必要的构造函数和初始化方法 ...

  6. InstallUtil.exe版本引起安装windows services 服务遇到的问题,System.BadImageFormatException

    原文:把程序安装成windows服务的过程及遇到的问题 做好了定时任务的程序,要把它放在服务器上,作为windows服务运行,也就是说,退出登录,用户注销后程序任然在后台运行. 将exe程序发布为服务 ...

  7. QList, QLinkedList, QVector, QStack, QQueue的区别,以前也没见过QCache,而且可以自定义cost

    http://doc.qt.io/qt-4.8/containers.html http://doc.qt.io/qt-4.8/qcache.html

  8. 【Windows10 IoT开发系列】Powershell命令行实用程序

    原文:[Windows10 IoT开发系列]Powershell命令行实用程序 更新帐户密码: 强烈建议你更新默认的管理员帐户密码.若要更新帐户密码,你可以发出以下命令: net user Admin ...

  9. 为什么360、百度、腾讯出的Mac端云盘客户端都只有同步盘?(用户量小,同步盘开发成本低,Linux下都没有客户端)

    如题,顾名思义,同步盘是用来同步的,不具备增量的功能,像这三家在Windows端出的客户端都是即有同步也有增量的. 陆续出来的,可能大家更多的是跟随策略,不得不提dropbox是这样的形式.mac电脑 ...

  10. [Leetcode]Single Number && Single Number II

    Given an array of integers, every element appears twice except for one. Find that single one. 非常简单的一 ...