基本介绍

  synchronized是Java实现同步的一种机制,它属于Java中关键字,是一种jvm级别的锁。synchronized锁的创建和释放是此关键字控制的代码的开始和结束位置,锁是有jvm控制的创建和释放的,正是因为这一点,synchronized锁不需要手动释放,哪怕是代码出现异常,jvm也能自动释放锁。同时jvm也记录的使用锁的线程,以及哪些线程出现了死锁这非常有利于我们排查问题。

优缺点

  优点

  1.synchronized所不用手动释放锁,即便抛出异常jvm也是让线程自动释放锁

  2.当 JVM 用 synchronized 管理锁定请求和释放时,JVM 在生成线程转储时能够包括锁定信息。这些对调试非常有价值,因为它们能标识死锁或者其他异常行为的来源

  缺点

  1.使用synchronized如果其中一个线程不释放锁,那么其他需要获取锁的线程会一直等待下去,等待的线程不能中途中断,直到使用完释放或者出现异常jvm会让线程自动释放锁

  2.也无法通过投票得到锁,如果不想等下去,也就没法得到锁

  3.同步还要求锁的释放只能在与获得锁所在的堆栈帧相同的堆栈帧中进行,多数情况下,这没问题(而且与异常处理交互得很好),但是,确实存在一些非块结构的锁定更合适的情况
  4.在激烈争用情况下更佳的性能,也即是如果多个线程都只是进行读操作,所以当一个线程在进行读操作时,其他线程只能等待无法进行读操作,性能比较低。因为当 JVM 用 synchronized 管理锁定请求和释放时,JVM 在生成线程转储时能够包括锁定信息,这些虽然对调试非常有价值,因为它们能标识死锁或者其他异常行为的来源,但是这势必会增大资源的消耗和耗时增加。

synchronized中锁的级别

偏向锁

  HotSpot作者经过研究发现,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入偏向锁。

  线程1检查对象头中的Mark Word中是否存储了线程1,如果没有则CAS操作将Mark Word中的线程ID替换为线程1。此时,锁偏向线程1,后面该线程进入同步块时不需要进行CAS操作,只需要简单的测试一下Mark Word中是否存储指向当前线程的偏向锁,如果成功表明该线程已经获得锁。如果失败,则再需要测试一下Mark Word中偏向锁标识是否设置为1(是否是偏向锁),如果没有设置,则使用CAS竞争锁,如果设置了,则尝试使用CAS将偏向锁指向当前线程

偏向锁的竞争结果:

根据持有偏向锁的线程是否存活

1.如果不活动,偏向锁撤销到无锁状态,再偏向到其他线程
2.如果线程仍然活着,则升级到轻量级锁

偏向锁在Java6和Java7中默认是开启的,但是在应用程序启动几秒后才激活,如果有必要可以关闭延迟:
-XX:BiasedLockingStartupDelay=0

如果确定应用程序中所有的锁通常情况下处于竞争状态,可以通过JVM参数关闭偏向锁:
-XX:-UseBiasedLocking=false,那么程序默认会进入轻量级锁。
-XX:BiasedLockingStartupDelay=0 -XX:+TraceBiasedLocking

轻量级锁

1.线程在执行同步块之前,JVM会在当前栈桢中创建用于存储锁记录的空间(Lock record),并将对象头中的Mark Word复制到锁记录中(Displaced Mark Word)。
2.然后线程尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针
3.如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程尝试使用自旋来获取锁

重量级锁

偏向锁、轻量级锁、重量级锁的优缺点

1.偏向锁是为了避免某个线程反复获得/释放同一把锁时的性能消耗,如果仍然是同个线程去获得这个锁,尝试偏向锁时会直接进入同步块,不需要再次获得锁。

2.而轻量级锁和自旋锁都是为了避免直接调用操作系统层面的互斥操作,因为挂起线程是一个很耗资源的操作。
为了尽量避免使用重量级锁(操作系统层面的互斥),首先会尝试轻量级锁,轻量级锁会尝试使用CAS操作来获得锁,如果轻量级锁获得失败,说明存在竞争。但是也许很快就能获得锁,就会尝试自旋锁,将线程做几个空循环,每次循环时都不断尝试获得锁。如果自旋锁也失败,那么只能升级成重量级锁。
3.可见偏向锁,轻量级锁,自旋锁都是乐观锁。

多线程之Synchronized锁的基本介绍的更多相关文章

  1. JAVA多线程之Synchronized关键字--对象锁的特点

    一,介绍 本文介绍JAVA多线程中的synchronized关键字作为对象锁的一些知识点. 所谓对象锁,就是就是synchronized 给某个对象 加锁.关于 对象锁 可参考:这篇文章 二,分析 s ...

  2. 【J2SE高速进阶】——多线程之synchronized

    我和老婆去银行取钱 有一天,和老婆打了个赌.如今我的银行账号里共同拥有5000块钱.我们去银行同一时候取钱,看我俩能不能同一时候取出5000来....(PS:打赌的代价是:假设都能取出5000,那这1 ...

  3. JAVA多线程之Synchronized、wait、notify实例讲解

    一.Synchronized synchronized中文解释是同步,那么什么是同步呢,解释就是程序中用于控制不同线程间操作发生相对顺序的机制,通俗来讲就是2点,第一要有多线程,第二当多个线程同时竞争 ...

  4. 并发编程之synchronized锁(一)

    一.设计同步器的意义 多线程编程中,有可能会出现多个线程同时访问同一个共享.可变资源的情况,这个资源我们称之其为临界资源:这种资源可能是:对象.变量.文件等. 共享:资源可以由多个线程同时访问 可变: ...

  5. Java多线程之synchronized线程锁

    package org.study2.javabase.ThreadsDemo.sync; /** * @Auther:GongXingRui * @Date:2018/9/18 * @Descrip ...

  6. Java——多线程之Lock锁

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

  7. Java多线程之synchronized(五)

    上篇介绍了用synchronized修饰static方式来实现“Class 锁”,今天要介绍另一种实现方式,synchronized(class)代码块,写法不一样但是作用是一样的.下面我附上一段代码 ...

  8. Java多线程之synchronized(四)

    前面几章都是在说synchronized用于对象锁,无论是修饰方法也好修饰代码块也好,然而关键字synchronized还可以应用到static静态方法上,如果这样写,那就是对当前的*.java文件所 ...

  9. Java多线程之synchronized及其优化

    Synchronized和同步阻塞synchronized是jvm提供的同步和锁机制,与之对应的是jdk层面的J.U.C提供的基于AbstractQueuedSynchronizer的并发组件.syn ...

随机推荐

  1. linux各文件夹含义和作用

    原文链接:https://blog.csdn.net/okyoung188/article/details/76315774 1.linux下各文件夹的意义:     /bin:是binary的缩写, ...

  2. nginx+iis使用

    一.nginx的介绍 nginx是由俄罗斯人开发的一款高性能的http和反向代理服务器,也可以用来作为邮件代理.相比较于其他的服务器,具有占用内存少,稳定性高等优势 Nginx相关地址 源码:http ...

  3. Visual studio 编辑combobox程序卡死的问题

    问题描述:使用vs2017开发一个winform小程序,一用combobox就卡死. 问题解决:关闭有道词典的取词功能. 软件开多了,就容易有冲突啊!

  4. javascript中数组的方法

    数组的方法 1.concat():连接两个或多个数组 2.indexOf(arg): ​ 查找数组中的arg元素,如果没有,则返回-1,如果有,则返回该元素的最小下标 ​ lastIndexOf(ar ...

  5. openwrt MT7628 编译前更改为DHCP,root 密码、ssid、时区、主机名

    一.设置为DHCP动态获取ip地址 在:/home/OpenWrt/openwrt_CC_mt76xx_zhuotk_source/ 目录下,新建文件名/files/etc/config. 将配置好的 ...

  6. jackson对日期的处理(序列化与反序列化)

    https://blog.csdn.net/cover1231988/article/details/76021478

  7. mysql的配置说明

    查询最高内存占用 使用以下命令可以知道mysql的配置使用多少 RAM SELECT ( @@key_buffer_size + @@query_cache_size + @@innodb_buffe ...

  8. numpy的基础运算2-【老鱼学numpy】

    numpy的基础运算中还有很多运算,我们这里再记录一些. 最小/大值索引 前面一篇博文中我们讲述过如何获得数组中的最小值,这里我们获得最小/大值的索引值,也就是这个最小/大值在整个数组中位于第几位. ...

  9. Android-动态权限获取

    声明权限: 首先在清单文件中写出相应权限 <!--存储权限--> <uses-permission android:name="android.permission.WRI ...

  10. Linux基础系统优化

    Linux的网络功能相当强悍,一时之间我们无法了解所有的网络命令,在配置服务器基础环境时,先了解下网络参数设定命令. ifconfig 查询.设置网卡和ip等参数 ifup,ifdown    脚本命 ...