synchronized关键字

一、synchronized锁原理

每一个Java对象内部都只有一个锁,如果使用synchronized使一个线程获取了某一个对象的锁之后,其它线程就无法获取这个对象的锁了,因为只有一个锁,其他线程只能等这个线程释放这个锁。

二、synchroniaze的使用

https://www.iamshuaidi.com/1082.html
https://zhuanlan.zhihu.com/p/346028951
1.修饰实例方法
2.修饰静态方法
3.修饰代码块

类锁与对象锁

三、monitor锁

https://segmentfault.com/a/1190000022421298

1.定义

Monitor称为内部锁或者Monitor锁,可以理解为一个同步工具或一种同步机制,通常被描述为一个对象。Monitor对象存在于每个Java对象的对象头中,所以每个对象都可以获得锁。
当一个线程访问同步代码块时,首先是需要得到锁才能执行同步代码,当退出或者抛出异常时必须要释放锁。
在这里插入图片描述

//this加锁
public class SynchronizedDemo {
    public void method() {
        synchronized (this) {
            System.out.println("Method 1 start");
        }
    }
}

查看反编译后结果:
在这里插入图片描述

2.monitor锁获取与释放

1.线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者;
如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1;
如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权;
2.线程执行monitorexit指令用来释放monitor,执行该指令的线程必须是monitor的所有者。指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。
注意:monitorexit指令出现了两次,第1次为正常释放monitor;第2次为发生异常时释放monitor。

综上所述,Synchronized的语义底层是通过一个monitor的对象来完成。

3.Java Monitor 的工作机理具体如下:

https://www.jianshu.com/p/6fe4bc3374a2Java Monitor工作机理
线程进入同步方法中:
1.为了继续执行临界区代码,线程必须获取 Monitor 锁。如果获取锁成功,将成为该监视者对象的拥有者。任一时刻内,监视者对象只属于一个活动线程(The Owner)
2.拥有监视者对象的线程可以调用 wait() 进入等待集合(Wait Set),同时释放监视锁,进入等待状态。
3.其他线程调用 notify() / notifyAll() 接口唤醒等待集合中的线程,这些等待的线程需要重新获取监视锁后才能执行 wait() 之后的代码。
4.同步方法执行完毕了,线程退出临界区,并释放监视锁。

4.对象头

https://editor.csdn.net/md?articleId=120488487
在JVM中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充。如下图所示:
在这里插入图片描述
对象头主要包括两部分数据:Mark Word(标记字段)和 Class Pointer(类型指针)。

Class Pointer 是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
Mark Word 用于存储对象自身的运行时数据,比如哈希码、锁状态标识、GC年龄等信息。
Java对象头具体结构描述如下:
在这里插入图片描述
锁也可以分为无锁、偏向锁、轻量级锁和重量级锁4种状态,每种都会有对应的标志位
在这里插入图片描述
当一个线程获取到锁之后,在锁的对象头里面会有一个指向线程栈中锁记录(Lock Record)的指针。当我们判断线程是否拥有锁时只要将线程的锁记录地址和对象头里的指针地址进行比较就行。

5.Lock Record(锁记录)

在线程进入同步代码块的时候,如果此同步对象没有被锁定,即它的锁标志位是01,则虚拟机首先在当前线程的栈中创建我们称之为“锁记录(Lock Record)”的空间,用于存储锁对象的Mark Word的拷贝。

Lock Record是线程私有的数据结构,每一个线程都有一个可用Lock Record列表。每一个被锁住的对象Mark Word都会和一个Lock Record关联(对象头的MarkWord中的Lock Word指向Lock Record的起始地址),同时Lock Record中有一个Owner字段存放拥有该锁的线程的唯一标识,表示该锁被这个线程占用。
如下图所示为Lock Record的内部结构:
在这里插入图片描述


https://tech.meituan.com/2018/11/15/java-lock.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值