Java synchronized锁详解

Java synchronized锁详解

Synchronized关键字的两种用法

  1. 修饰实例方法
    作用于非静态方法,此时synchronized保护的是TheadA的一个对象的method方法,是对象锁
    Java synchronized锁详解_第1张图片
    Java synchronized锁详解_第2张图片
  2. 修饰静态方法
    作用于静态方法,此时锁为类锁,不同对象使用该方法时都会发生互斥现象.
    Java synchronized锁详解_第3张图片
  3. 修饰代码块
    当其为this时,则是对象锁,当起为this.getClass()时,则是类锁.
    Java synchronized锁详解_第4张图片

Synchronized底层原理

1.理解Java对象头和管程(monitor)

  • 实例变量:存放类的属性数据信息,包括父类的属性信息,如果是数组的实例部分还包括数组的长度,这部分内存按4字节对齐。

  • 填充数据:由于虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐,这点了解即可。

  • 对象头的主要结构是由Mark Word和Class Metadata Address组成

    Mark Word 字段储存着,锁的状态,轻量级锁指针,重量级锁指针.
    重量级锁也就是通常说synchronized的对象锁,锁标识位为10,其中指针指向的 monitor对象(也称为管程或监视器锁)的起始地址。每个对象都存在着一个 monitor 与之关联,对象与其 monitor 之间的关系有存在多种实现方式,如monitor可以与对象一起创建销毁或当线程试图获取对象锁时自动生成,但当一个 monitor 被某个线程持有后,它便处于锁定状态

    Monitor由ObjectMonitior类实现

ObjectMonitor中有三个部分

  • waitSet队列

  • EntryList队列

  • owner区域

多线程访问同步代码(monitorenter)时.

  1. 进入EntryList

  2. 获取要访问对象的monitor

  3. Monitor.owner=当前线程;

  4. monitor.count++;

  5. if 线程调用wait方法,monitor.owner=null,monitor–,线程进入waitSet区堵塞

  6. if 线程调用notify方法,waitSet中的任意一个线程根据不同的策略进入owner区或者entryList区.

  7. 线程运行完毕,monitor.owner=null.monitor–,线程离开

    Java synchronized锁详解_第5张图片

2.Syn底层实现

有Synchronized标志的方法将有一个ACC_SYNCHRONIZED标志来表示其为一个同步方法,当线程访问到标志时, 执行monitorenter指令,当前线程将试图获取 objectref(即对象锁) 所对应的 monitor 的持有权,并设置monitor计数器值为1, 直到正在执行线程执行完毕,即monitorexit指令被执行,执行线程将释放 monitor(锁)并设置计数器值为0 ,其他线程将有机会持有 monitor

3.Java对Synchronized锁的优化

无锁->偏向锁->轻量级锁->重量级锁

  • 偏向锁:

    当锁不仅不存在多线程竞争,而且总是由同一线程多次获得,因此为了减少同一线程获取锁(会涉及到一些CAS操作,耗时)的代价而引入偏向锁。偏向锁的核心思想是,如果一个线程获得了锁,那么锁就进入偏向模式,此时Mark Word 的结构也变为偏向锁结构,当这个线程再次请求锁时,无需再做任何同步操作,即获取锁的过程,这样就省去了大量有关锁申请的操作,从而也就提供程序的性能。

  • 轻量级锁:

    轻量级锁所适应的场景是线程交替执行同步块的场合,如果存在同一时间访问同一锁的场合,就会导致轻量级锁膨胀为重量级锁。

  • 自旋锁:

    基于在大多数情况下,线程持有锁的时间都不会太长,如果直接挂起操作系统层面的线程可能会得不偿失,毕竟操作系统实现线程之间的切换时需要从用户态转换到核心态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高,因此自旋锁会假设在不久将来,当前的线程可以获得锁,因此虚拟机会让当前想要获取锁的线程做几个空循环(这也是称为自旋的原因),一般不会太久,可能是50个循环或100循环,在经过若干次循环后,如果得到锁,就顺利进入临界区。如果还不能获得锁,那就会将线程在操作系统层面挂起

4关于synchronized 可能需要了解的关键点

1. synchronized的可重入性

Java synchronized锁详解_第6张图片

你可能感兴趣的:(Java多线程)