Java并发系列之Synchronized

本文详细探讨了Java中的synchronized关键字,包括锁对象、Markword、偏向锁、锁膨胀、轻量级锁、自旋锁/自适应自旋锁、互斥锁(重量级锁)等概念。讲解了synchronized如何在Java虚拟机中实现加锁,并介绍了从1.6版本开始的优化措施,如偏向锁和轻量级锁的引入,以及它们在不同场景下的适用性。通过对锁状态的变化,揭示了synchronized的升级路径:从偏向锁到轻量级锁,再到重量级锁。
摘要由CSDN通过智能技术生成

每一个刚接触多线程并发编程的同学,当被问到,如果多个线程同时访问一段代码,发生并发的时候,应该怎么处理?

我相信闪现在脑海中的第一个解决方案就是用synchronized,用锁,让这段代码同一时间只能被一个线程执行。
我们也知道,synchronized关键字可以用在方法上,也可以用在代码块上,如果要使用synchronized,我们一般就会如下使用:

public synchronized void doSomething() {
    //do something here
}

或者

synchonized(LockObject) {
    //do something here
}

那么实际上,synchronized关键字到底是怎么加锁的?锁又长什么样子的呢?关于锁,还有一些什么样的概念需要我们去认识,去学习,去理解的呢?

以前在学习synchronized的时候,就有文章说, synchronized是一个很重的操作,开销很大,不要轻易使用,我们接受了这样的观点,但是为什么说是重的操作呢,为什么开销就大呢?

到java 1.6之后,java的开发人员又针对锁机制实现了一些优化,又有文章告诉我们现在经过优化后,使用synchronized并没有什么太大的问题了,那这又是因为什么原因呢?到底是做了什么优化?

那今天我们就尝试着从锁机制实现的角度,来讲述一下synchronized在java虚拟机上面的适应场景是怎么样的。

由于java在1.6之后,引入了一些优化的方案,所以我们讲述synchronized,也会基于java1.6之后的版本。

锁对象

首先,我们要知道锁其实就是一个对象,java中每一个对象都能够作为锁。

所以我们在使用synchronized的时候,
1. 对于同步代码块,就得指定锁对象。
2. 对于修饰方法的synchronized,默认的锁对象就是当前方法的对象。
3. 对于修饰静态方法的synchronized,其锁对象就是此方法所对应的类Class对象。

我们知道,所谓的对象,无非也就是内存上的一段地址,上面存放着对应的数据,那么我们就要想,作为锁,它跟其它的对象有什么不一样呢?怎么知道这个对象就是锁呢?怎么知道它跟哪个线程关联呢?它又怎么能够控制线程对于同步代码块的访问呢?

Markword

可以了解到在虚拟机中,对象在内存中的存储分为三部分:
1. 对象头
2. 实例数据
3. 对齐填充

其中,对象头填充的是该对象的一些运行时数据,虚拟机一般用2到3个字宽来存储对象头。
1. 数组对象,会用3个字宽来存储。
2. 非数据对象,则用2个字宽来存储。

其结构简单如下:

长度 内容 说明
32/64bit Markword hashCode,GC分代年龄,锁信息
32/64bit
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值