Java并发编程基础-锁-synchonized

  • 前言:

      synchonized是java中广泛意义的锁,通常都会称之为重量锁。自从JDK1.6开始对synchonized进行优化,synchonized在某些状况下也会转变为偏向锁、轻量锁、重量锁能够认为synchonized关键字是几种锁的封装。java

  • 用法:
    • 修饰方法,当有线程调用这个方法时,会锁定该方法的实例对象,不容许其余线程进行操做,若是方法是静态的,锁的是该类型的Class对象,示例以下:
      public synchronized void methodName
    • 修饰代码块,当有线程使用代码块时,会锁定代码块,不容许其余线程进行操做,锁的是()里面的对象,示例以下:
      public void methodName(){
          synchronized (lockObj){
              //logic
          }
      }
      代码中的lockObj为一个对象,被称为监视器(monitor),能够使用this,或者任意Object对象,用于存储锁的相关信息。
  • 原理:
           使用javap反编译拥有synchonized代码块的方法,发现synchonized代码块开始和结束(有异常)的地方分别有monitorentermonitorexit指令,以下图所示:



          当执行到monitorenter时,获取monitor(即代码中的lockObj)的全部权,执行到monitorexit,释放monitor的全部权,synchonized方法原理也相似。
  • 底层实现:
          synchonized将锁的信息存在了Java对象头的MarkWord里,32位和64位操做系统Java对象头的结构以下图所示:



          前面提到synchonized关键字包含有几种状态,从无锁状态->偏向锁->轻量锁->重量锁 依次变化,锁只能升级,不能降级,32位虚拟机MarkWord中存储的锁状态信息以下:



          推荐使用openjdk的JOL包来观察MarkWord,一个无锁状态的截图以下(图中01为锁标识位):



          几种锁的状态升级过程比较复杂,另开一贴具体说明。
  • 坑:
    • 使用synchronized修饰代码块时,lock对象须要是全局的对象,若是lockObj在代码块所在方法内进行初始化,那么锁定无效,由于使用的锁信息存储在了不一样的对象中。
    • 使用JOL观察MarkWord时,低位优先打印,所以上面无锁状态的截图中01才是锁标志位。

参考书籍及网址:编程

  • 《Java并发编程的艺术》
  • 《深刻理解Java虚拟机》

PS:研究基于MAC+Idea+JDK1.8 64位并发

Keep Calm and Carry on!优化

相关文章
相关标签/搜索