synchronized与ReentrantLock区别

功能区别
  1. 在未优化前synchronized是属于重量级锁,系统切换用户态与核心态来实现阻塞与唤醒

  2. Synchronized的使用比较方便简洁,并且由编译器去保证锁的加锁和释放,而ReenTrantLock需要手工声明来加锁和释放锁,
    为了避免忘记手工释放锁造成死锁,需要lock()和unlock()方法配合try/finally语句块来完成

JAVA使用synchronized实现互斥同步线程安全以及原理
  1. synchronized经过编译后会在同步代码块前后形成monitorenter和monitorexit,
    任何对象都有一个 Monitor 与之相关联,当且一个 Monitor 被持有之后,他将处于锁定状态。
    线程执行到 monitorenter 指令时,将会尝试获取对象所对应的 Monitor 所有权,即尝试获取对象的锁,
    如果当前线程拥有那个对象的锁,把锁的计数器+1,相应的但执行monitorexit指令时会把锁的计数
    器-1即释放锁!
synchronized锁优化
  1. jdk1.6之后引入一项锁优化,加入偏向锁,轻量级锁

    1. 轻量级锁:主要是为了减少传统的重量级锁使用操作系统互斥产生的性能消耗
      (因为重量级锁如果要阻塞或者唤醒一个线程,都需要操作系统介入,
      需要从用户态切换为核心态,在状态切换需要消耗处理器时间)。
      如果有多线程竞争同一把锁,则会膨胀为重量级锁竞争,该锁的获取与释放需要CAS操作

    2. 偏向锁:主要是消除数据在无竞争的情况下同步,在线程执行过程中,该锁没有被其他线程获取,则持有偏向锁的线程
      将永远不需要再进行同步,减少CAS操作

  2. 轻量级锁获取流程

    Mark Word:每个对象的对象头信息,该对象头分为两部分信息的。
    第一部分:存储对象自身运行时的数据,如哈希码,GC分代年龄,是实现轻量级锁与偏向锁关键
    第二部分:存储指向方法区对象类型数据的指针

    1. 当线程访问同步代码块,会先检查该同步对象是否被锁定,如果没有则 JVM 首先将在当前线程的栈帧中,
      建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的 Mark Word的 拷贝
      (官方把这份拷贝加了一个 Displaced 前缀,即 Displaced Mark Word),否则执行 3

    2. JVM 利用 CAS 操作尝试将对象的 Mark Word 更新为指向 Lock Record 的指正。如果成功,
      表示竞争到锁,则将锁标志位变成 00(表示此对象处于轻量级锁状态)。否则执行 3

    3. 判断当前对象的 Mark Word 是否指向当前线程的栈帧?如果是,则表示当前线程已经
      持有当前对象的锁,则直接执行同步代码块;否则,只能说明该锁对象已经被其他线程
      抢占了,此时轻量级锁膨胀为重量级锁,锁标志状态值变为 10,后面等待的线程也要进入
      阻塞状态

  3. 释放锁

    1. 取出在获取轻量级锁保存在 Displaced Mark Word 中 数据

    2. 使用 CAS 操作将取出的数据替换当前对象的 Mark Word 中。
      如果成功,则说明释放锁成功;否则说明有其他线程尝试获得
      该锁,要在释放锁的同时唤醒被挂起的锁

  4. 偏向锁

    1. 在jdk1.6之后,当锁对象第一次被线程获取时,JVM会把对象头中标志位设为01,即偏向模式

    2. CAS操作把获得该的锁的线程ID记录在Mark Word中,如果成功则执行同步代码块,如果失败
      则通过CAS竞争锁,成功则执行同步代码块,如果失败则将锁升级为轻量级锁.

  5. 偏向锁撤销

    1. 偏向锁的释放采用了一种只有竞争才会释放锁的机制,线程是不会主动去释放偏向锁,需要等待其他线程来竞争

    2. 当有另一个线程尝试获得该锁,根据所当前的被锁定状态,撤销偏向,恢复到无锁状态01,或轻量级锁状态00

ReentrantLock
  1. ReentrantLock是java.util.concurrent包下提供的一套可重入互斥锁

  2. 相对于synchronized提供以下功能操作

    1. 等待可中断,
      持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待,这相当于Synchronized来说可以避免出现死锁的情况。
      通过lock.lockInterruptibly()来实现这个机制。

    2. 多个线程等待同一个锁时,必须按照申请锁的时间顺序获得锁,Synchronized锁非公平锁

    3. ReenTrantLock提供了一个Condition类,用来实现分组唤醒需要唤醒的线程们。

  3. ReenTrantLock实现的原理:
    ReenTrantLock的实现是一种自旋锁,通过循环调用CAS操作来实现加锁,来避免了使线程进入内核态的阻塞状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值