了解线程同步机制---Synchronized锁

线程的同步机制(Synchronized锁)

由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入锁机制 synchronized,当一个线程获得对象的排它锁,独占资源,其他线程必须等待,使用后释放即可.存在以下问题

  1. 一个线程持有锁会导致其他所有需要此锁的线程挂起
  2. 在多线程竞争下,加锁,释放锁会导致比较多的上下文切换和调度延时,引起性能问题
  3. 如果一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题

解决安全性

由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们只需要针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:

synchronized方法和synchronized块
同步方法:public synchronized void method(int args){}

synchronized 方法控制对"对象"的访问,每个对象对应一把锁,每个 synchronized 方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行

缺陷:若将一个大的方法申明为 synchronized 将会影响效率

同步监视器的执行过程

(1)第一个线程访问,锁定同步监视器,执行其中代码
(2)第二个线程访问,发现同步监视器被锁定,无法访问
(3)第一个线程访问完毕,解锁同步监视器
(4)第二个线程访问,发现同步监视器没有锁,然后锁定并访问
(5)继续执行以上操作

历史

在JDK5之前,Java中的锁是通过关键字synchronized来实现的,而在JDK5之后Lock接口的出现使得锁的使用更加的灵活。同时在JDK6开始对synchronized关键字进行了锁升级的优化,使其能够适用于更多的场景,不再是严格意义上的重量级锁

定义

synchronized是 JVM 中实现的一种锁,同时也是内置的java关键字,说明我们无法判断获取锁的状态。锁的获取和释放方式分别是monitorentermoniterexit的一个指令,会自动释放锁,是一种可重入锁,不可以中断的、非公平。在线上分为了偏向锁、轻量级锁以及重量级锁,其中偏向锁在1.6是默认开启的,轻量级锁在多线程竞争情况下会膨胀成重量级锁,也就是说有关于这个锁的数据都会保存在对象头中。适合锁少量的代码同步问题,是一把悲观锁

  • 偏向锁

偏向锁指的是当锁不存在多个线程竞争,并且经常由一个线程获取锁对象时,为了让线程获取锁的代价更低,在锁对象的mark word中保存了当前获取锁对象线程的线程ID,下次该线程要获取锁的时候可以不使用CAS的方式获取锁,而是直接通过比较线程ID来再次获取锁对象

  • 轻量级锁

轻量级锁状态发生在当有多个线程访问同步代码块,但是访问时间是错开的,彼此之间没有竞争的时候。(注意偏向锁是发生在同一个线程反复访问同步代码块的时候)

轻量级锁状态的记录不再跟偏向锁一样在对象的mark word域中记录thread id,而是使用了线程栈中的栈帧的锁记录结构来记录轻量级锁状态

  • 重量级锁

重量级锁和一个Monitor对象有关。每个Java对象都可以关联一个Monitor对象,如果使用synchronized关键字给对象加上重量级锁的时候,锁对象的mark word域就会指向Monitor对象

可重入锁:在自己以获取一把锁的状态下,⾃⼰是可以重复获取此锁的

可重入锁又称递归锁,是指同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提是锁对象得是同一个对象),不会因为之前已经获取过锁还没有释放而阻塞

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naijia_OvO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值