Java多线程系列2: 锁

Java多线程系列2: 锁

本文是作者的读博客笔记和心得整理,也引用了一些比较好的博客文章,部分内容来源于网络,如有侵权,请联系作者。

什么是锁

锁即为保护一个共享代码块(临界区)只能被一个线程进行访问.使用synchronized,在public后面,返回值前面

被锁保护的共享变量在释放锁之前是对其他线程不可见的,在B拿到锁之后立刻可见.

主要的操作是当线程A释放锁的时候,JMM会立刻把A的共享变量刷新到主内存去.这样B拿到锁的时候,B的本地内存被置为无效,从而使得B必须去主内存中获取.

Synchronized关键字

首先,Java中的所有对象都可以作为锁.
普通同步方法,锁的是当前实例对象
静态同步方法锁的是当前类对象
同步方法块锁的是括号里面对象

Java对象头

对象头主要包括两部分的数据:Mark Word(标记字段),KClass Pointer(类型指针)
类型指针是对象指向它的类元数据的指针,用来确定这个对象是哪个类的
Mark Word用于存储对象自身运行时的数据,是实现轻量级锁和偏向锁的关键。

Monitor

每个对象都带有这么一个内部锁,是线程私有的一个数据结构,每一个线程都有一个monitor record列表,每一个被锁住的对象都会和一个monitor关联(对象头的MarkWord中的LockWord指向monitor的起始地址),同时monitor中有一个Owner字段存放拥有该锁的线程的唯一标识,表示该锁被这个线程占用。

锁优化

锁主要存在4种状态,无锁,偏向锁,轻量级锁,重量级锁,会随着竞争的激烈而逐渐升级,但是锁是不可以降级的,这样是为了提高获得和释放锁的效率

自旋锁

线程的阻塞和唤醒需要CPU从用户态转换为核心态,频繁的阻塞和唤醒给系统的并发造成很大的压力。
自旋锁就是为了解决锁状态只需要持续很短时间的case

自旋的意思就是让来获取该锁的线程不要立刻挂起,而是等待一段时间看看是否锁很快会被释放。

等待的时间就是执行一段无意义的循环,如果等待了一段时间锁还是没释放,那就挂起。

适应自旋锁

如果上次自旋成功,下次就多自旋一些。这样虚拟机会越来越聪明。

锁消除

当JVM判断变量不存在冲突问题时,就会自动把锁去掉.

锁粗化

连续的加锁解锁会被移动到for循环之外,比如vector的for循环add.

轻量级锁

使用轻量级锁主要是为了降低重量级锁的消耗.
轻量级锁也就是先给一个对象加锁,然后过一段时间判断是否有人尝试获取该锁,如果有人尝试获取,说明当前竞争压力很大,所以需要变为重量级锁.

注意如果在有竞争的情况下,轻量级锁会更慢

CAS操作

需要输入两个值,一个旧值和一个新值,如果旧值和当前值相同,则更新旧值为新值.
如果旧值和当前值不同,则什么都不做.
这是一个原子操作.

偏向锁

偏向锁的意思是,当拿到锁之后,先置为偏向状态,然后去竞争锁,如果拿不到,说明存在竞争,那么就升级为轻量级锁.
偏向锁不会主动释放,只有在有其他线程竞争的时候才会释放.要等待到全局安全点了再升级锁.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值