并发编程带来的挑战

一、 简述锁升级的流程和原理

为了防止多线程访问共享资源造成线程阻塞的问题,并不会立马对共享资源加重量级锁,使线程进入BLOCKING状态,而是先尝试加偏向锁,在一步步向轻量级锁、重量级锁膨胀的策略,如下图所示:

image.png

**偏向锁:**不存在资源竞争,资源总是由一个线程获取的情况下使用。在对象头存储了当前线程的id.

**轻量级锁:**如果偏向锁被关闭或者已经被其他线程获取,这种情况下抢占同步锁会膨胀到轻量级锁。轻量级锁会通过CAS操作(自旋),把锁对象的标记字段替换为一个指针指向当前线程栈帧中的LockRecord

**重量级锁:**多个线程获取同一个锁的时候,虚拟机就会阻塞未获取到锁的线程,并在目标锁释放的时候唤醒阻塞的线程。对象头存储了指向重量级锁的指针。

总结:

**偏向锁:**无实际竞争,且将来只有第一个申请锁的线程会使用锁。

**轻量级锁:**无实际竞争,多个线程交替使用锁;允许短时间的锁竞争。

**重量级锁:**有实际竞争,且锁竞争时间长。

二、Synchronized的原理

synchronized有三种方式来加锁,分别是:方法锁,对象锁synchronized(this),类锁synchronized(Demo.Class)。其中在方法锁层面可以有如下3种方式:

修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁

静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁

修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。

使用synchronized加锁会从低到高逐步升级, 无锁->偏向锁->轻量级锁->重量级锁

重量级锁通过对象内部的监视器(monitor)实现,一段被synchronized修饰的同步方法或者代码块时,该线程得先获取到sync
hronized修饰的对象对应的monitor,过程如下

image.png

三、线程是不是越多越好?为什么?

不是,由于硬件资源的限制,线程过多会造成线程阻塞,阻塞或者唤醒一个线程时,都需要操作系统来帮忙,这就需要从用户态转换到内核态,而转换状态是需要消耗很多时间的,有可能比用户执行代码的时间还要长。

四、wait和notify为什么要加锁
wait方法的语义有两个,一个是释放当前的对象锁、另一个是使得当前线程进入阻塞队列, 而这些操作都和监视器是相关的,所以wait必须要获得一个监视器锁。
而对于notify来说也是一样,它是唤醒一个线程,既然要去唤醒,首先得知道它在哪里?所以就必须要找到这个对象获取到这个对象的锁,然后到这个对象的等待队列中去唤醒一个线程。
作者:https://gper.club/articles/7e7e7f7ff3g5bgc0g69

最后

小编这些年深知大多数初中级工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此我收集整理了一份《2024年Java全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你需要这些资料,⬅专栏获取
录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

如果你需要这些资料,⬅专栏获取

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值