继续面试大纲系列文章。

  从这一篇开始,我们进入ava编程中的一个重要领域---多线程!多线程就像武学中对的吸星大法,理解透了用好了可以得道成仙,俯瞰芸芸众生;而滥用则会遭其反噬。

  在多线程编程中要渡的首个“劫”,则是Synchronized。了解其底层实现,无论是在面试中还是在平时工作中,都大有裨益。我们知其然,知其所以然,才能得心应手少挖坑。

  我们知道,多线程的核心思想是通过增加线程数量来并发的运行,来提高效率,也就是数量决胜论,而不是质量决胜(提高每个线程的处理能力)。多线程编程中面临的最大挑战,是如何解决多个线程同时修改一个公用的变量所带来的变量值不确定性问题。顺着这个思路分析,常用办法,无非就是,要么对变量动手,在一个线程修改时,变量值被锁定。要么是对修改的操作动手,在该段代码执行时,对其加锁,其他线程不可以在同一时刻进入该段代码执行。

  Synchronized,正是实现了后一种办法。

Synchronized

  1. 问:你平时涉及到多线程编程多不多?谈谈你对Synchronized锁的理解
  2. 分析:多从实现原理,工作机制来描述
  3. 答:
    1.   在多线程编程中,为了达到线程安全的目的,我们往往通过加锁的方式来实现。而Synchronized正是java提供给我们的非常重要的锁之一。它属于jvm级别加锁,底层实现是:在编译过程中,在指令级别加入一些标识来实现的。例如,同步代码块,会在同步代码块首尾加入monitorenter和monitorexit字节码指令,这两个指令都需要一个reference类型的参数,指明要加锁和解锁的对象,同步方法则是通过在修饰符上加acc_synchronized标识实现。在执行到这些指令(标识)时,本质都是获取、占有、释放monitor锁对象实现互斥,也就是说,同一时刻,只能有一个线程能成功的获取到这个锁对象。我们看一段加了synchronized关键字的代码编译后的字节码。编译前:

      1 public class test {
      2 public test() {
      3 }
      4 public static void main(String[] args) {
      5 synchronized(new Object()){
      6 int i = 0;
      7 }
      8 }
      9 }

      编译后:

      public class test extends java.lang.Object{
      public test();
      Code:
      0: aload_0
      1: invokespecial #1; //Method java/lang/Object."":()V
      4: nop
      5: return public static void main(java.lang.String[]);
      Code:
      0: new #2; //class Object
      3: dup
      4: invokespecial #1; //Method java/lang/Object."":()V
      7: dup
      8: astore_1
      9: monitorenter // Enter the monitor associated with object
      10: iconst_0
      11: istore_2
      12: nop
      13: aload_1
      14: monitorexit // Exit the monitor associated with object
      15: goto 23
      18: astore_3
      19: aload_1
      20: monitorexit // Be sure to exit monitor...
      21: aload_3
      22: athrow
      23: nop
      24: return
      Exception table:
      from to target type
      10 15 18 any
      18 21 18 any }

      重点关注14行,和20行。

    2.  在使用Synchronized时,用到的方法是wait和notify(或notifyAll),他们的原理是,调用wait方法后,线程让出cpu资源,释放锁,进入waiting状态,进入等待队列【第一个队列】。当有其他线程调用了notify或者notifyAll唤醒时,会将等待队列里的线程对象,移入阻塞队列【第二个队列】,状态是blocked,等待锁被释放后(这个释放时机,由虚拟机来决定,人为无法干预),开始竞争锁。
    3. Synchronized无法中断正在阻塞队列或者等待队列的线程。

  4.扩展:Synchronized提供了以下几种类型的锁:偏向锁、轻量级锁、重量级锁。在大部分情况下,并不存在多线程竞争,更常见的是一个线程多次获取同一个锁。那么很多的消耗,其实是在锁的获取与释放上。Synchronized一直在被优化,可以说Synchronized虽然推出的较早,但是效率并不比后来推出的Lock差。

  1.  偏向锁:在jdk1.6中引入,目的是消除在无竞争情况下的同步原语(翻译成人话就是,即使加了synchronized关键字,但是在没有竞争的时候,没必要去做获取-持有-释放锁对象的操作,提高程序运行性能)。怎么做呢?当锁对象第一次被线程A获取时,虚拟机会把对象头中的标志位设置为01,也就是代表偏向模式。同时把代表这个线程A的ID,通过CAS方式,更新到锁对象头的MarkWord中。相同的线程下次再次申请锁的时候,只需要简单的比较线程ID即可。以上操作成功,则成功进入到同步代码块。如果此时有其他线程B来竞争该锁,分两种情况做不同的处理:
    1. 如果线程A已执行完(并不会主动的修改锁对象的状态),会直接撤销锁对象的状态为未锁定,标志位为00;
    2. 如果线程A还在持有该锁,则锁升级为轻量级锁。  
  2. 轻量级锁:也是JDK1.6中引入的,轻量级,是相对于使用互斥量的重量级锁来说的。线程发生竞争锁的时候,不会直接进入阻塞状态,而是先尝试做CAS修改操作,进入自旋,这个过程避免了线程状态切换的开销,不过要消耗cpu资源。详细过程是:
    1.   线程尝试进入同步代码块,如果锁对象未被锁定,在当前线程对应的栈帧中,建立锁记录的空间,用于存储锁对象Mark Word的拷贝。
    2. 然后JVM用CAS方式尝试将锁对象的MarkWord内容替换为指向前述“锁记录”的指针。如果成功,当前线程则持有了锁,处于轻量级锁定状态;如果失败,会首先检查当前MarkWord是否已经指向当前线程栈帧的“锁记录”,如果是,就说明当前线程已经拥有了这个锁,直接重入即可。否则就表明是其他线程持有锁,那么进入自旋(其实就是重试CAS修改操作)。
    3. 释放锁时,是使用CAS来讲MarkWord和“锁记录”里的内容互换。如果成功,成功释放;如果事变,表明当前锁存在竞争(被其他线程修改了MarkWord里的数据),此时,锁会升级为重量级锁。
  3. 重量级锁:也就是我们使用的互斥量方式实现的锁,当存在多线程竞争时,只要没拿到锁,就会进入阻塞状态,主要消耗是在阻塞-唤起-阻塞-唤起的线程状态切换上。
  4. 上面介绍的三种类型的锁,是JVM来负责管理使用哪种类型锁,以及锁的升级(注意,没有降级)。
  5. 这里涉及到锁升级,对象头MarkWord等内容,如果详细说,可能又是一大篇文章了,如果大家感兴趣,可以另起一篇。
  6. synchronized就先介绍到这里,下一篇预告:ReentrantLock相关
  7. 如果你看的爽,请点击右下角的“推荐”,是对小端坚持分享原创的最大鼓励。也可以关注小端的个人公众号 :   pnxsxb  ,会分享更多的原创技术文章。

欢迎扫描以下二维码:

BAT美团滴滴java面试大纲(带答案版)之三:多线程synchronized的更多相关文章

  1. BAT美团滴滴java面试大纲(带答案版)之三:多线程Lock

    继续面试大纲系列文章. 这是多线程的第二篇. 多线程就像武学中对的吸星大法,理解透了用好了可以得道成仙,俯瞰芸芸众生:而滥用则会遭其反噬. 在多线程编程中要渡的第二个“劫”,则是Lock.在很多时候, ...

  2. 金三银四跳槽季,BAT美团滴滴java面试大纲(带答案版)之一:Java基础篇

    Java基础篇: 题记:本系列文章,会尽量模拟面试现场对话情景, 用口语而非书面语 ,采用问答形式来展现.另外每一个问题都附上“延伸”,这部分内容是帮助小伙伴们更深的理解一些底层细节的补充,在面试中可 ...

  3. BAT美团滴滴java面试大纲(带答案版)之四:多线程Lock

    每天学习一点点 编程PDF电子书.视频教程免费下载:http://www.shitanlife.com/code 这是多线程的第二篇. 多线程就像武学中对的吸星大法,理解透了用好了可以得道成仙,俯瞰芸 ...

  4. Java面试大纲-java面试该做哪些准备,java开发达到这样的水平可以涨工资

    Java培训结束,面临的就是毕业找工作.在找工作时,就要针对性地做充分的面试准备.准备不充分的面试,完全是浪费时间,更是对自己的不负责. 上海尚学堂Java培训整理出Java面试大纲,其中大部分都是面 ...

  5. 2019滴滴java面试总结 (包含面试题解析)

    2019滴滴java面试总结  (包含面试题) 本人6年开发经验.今年年初找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.滴滴等公司offer,岗位是既有php也有Java后端开发,最终选择去了滴滴 ...

  6. Java面试宝典(2018版)

    置顶 2018年11月10日 23:49:18 我要取一个响亮的昵称 阅读数:8893    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/chen ...

  7. Java面试:投行的15个多线程和并发面试题

    多线程和并发问题已成为各种 Java 面试中必不可少的一部分.如果你准备参加投行的 Java 开发岗位面试,比如巴克莱银行(Barclays).花旗银行(Citibank).摩根史坦利投资公司(Mor ...

  8. Java面试:投行的15个多线程和并发面试题(转)

    多线程和并发问题已成为各种 Java 面试中必不可少的一部分.如果你准备参加投行的 Java 开发岗位面试,比如巴克莱银行(Barclays).花旗银行(Citibank).摩根史坦利投资公司(Mor ...

  9. 2019 滴滴java面试笔试总结 (含面试题解析)

       本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.滴滴等公司offer,岗位是Java后端开发,因为发展原因最终选择去了滴滴,入职一年时间了,也成为了面试官, ...

随机推荐

  1. Python 魔法方法简介

    1.什么是魔法方法? 魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一 ...

  2. (一)Maven简介

    Maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行”,是一个跨平台的项目管理工具.Maven主要服务于基于Java平台的项目构建.依赖管理和项目信息管理. 构建(build)是每一 ...

  3. Cannot obtain the required interface ("IID_IDBCreateCommand") from OLE DB provider "OraOLEDB.Oracle" for linked server xxxx

      今天遇到了一个关于LINKED SERVER查询报错的案例,链接服务器链接ORACLE数据库,测试没有错误,但是执行脚本的时候,报如下错误: Msg 7399, Level 16, State 1 ...

  4. HBase快速安装

    配置hbase-env.sh #JAVA_HOME 需要Java 1.7+ export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/ # Java CLA ...

  5. 使用netstat命名排查网络问题的参考指引

    原文链接:http://www.lookdaima.com/WebForms/WebPages/Blanks/Pm/Docs/DocItemDetail.aspx?id=69b487d0-8bf4-4 ...

  6. [福大软工] Z班 团队Beta阶段成绩汇总

    Beta敏捷冲刺得分 队伍名 1 2 3 4 5 总分 Dipper 10 10 10 10 10 50 SWSD 9 9 9 9 7 43 五成胜算 10 10 10 10 10 50 人月神教 0 ...

  7. Nginx使用教程(七):使用Nginx缓存之proxy cache

    定义缓存目录 <br\>使用您喜欢的文本编辑器打开/etc/nginx/nginx.conf,并在http {区域加入: proxy_cache_path  /var/www/cache ...

  8. Git无法提交,报错

    Failed at the ant-design-pro@2.2.1 lint-staged script. npm ERR! This is probably not a problem with ...

  9. 如何给30台centos7服务器分别增加相同的用户

    老大直接给了30台新鲜的生产服务器,要给每一台服务器增加一个用户,密码相同 难道我们要部署一个工具吗?这样对生产环境可能会产生影响,为了保证服务器的新鲜以及节约时间,研究了小半天,终于研究出一个不是很 ...

  10. wpf小技巧——datagrid 滚动条问题

    今天在项目中遇到了一个问题,datagrid 不出现滚动条了,拿出来给大家分享下,以作前车之鉴. 很简单的布局代码如下 <Window x:Class="DataGrid_AutoSi ...