synchronized锁原理详解

synchronized锁用法

// synchronized锁底层原理
public class SynchronizedTest03 {
    //修饰静态方法(同步方法)
    //代码块0(锁定的是当前类)
    public synchronized static void access0(){
        try {
            TimeUnit.MINUTES.sleep(1);
            System.out.println(Thread.currentThread().getName()+" is running");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //修饰非静态方法(同步方法)
    //代码块1(锁定的是当前对象的调用者)
    public synchronized void access1(){
        try {
            TimeUnit.MINUTES.sleep(1);
            System.out.println(Thread.currentThread().getName()+" is running");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //修饰非静态方法(同步代码块)
    //代码块2(锁定的是对象)this指的是当前对象
    public void access2(){
        synchronized(this){
            try {
                synchronized (this){
                    TimeUnit.MINUTES.sleep(1);
                }
                System.out.println(Thread.currentThread().getName()+" is running");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //代码块3(锁定的是CLASS类)(同步代码块)
    public void access3(){
        synchronized(SynchronizedTest03.class){//ClassLoader  class  -->  “堆”区生成一个Class对象:所有的对象
            //有Class对象的所有的对象都共同使用这一个锁
            try {
                TimeUnit.MINUTES.sleep(1);
                System.out.println(Thread.currentThread().getName()+" is running");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SynchronizedTest03 demo = new SynchronizedTest03();
        for (int i = 0; i < 5; i++) {
            new Thread(demo::access2).start();
        }
    }
}

锁的分类:

      1.对象锁

            synchronized(this|object) {} 修饰非静态方法

            在 Java 中,每个对象都会有一个 monitor 对象,这个对象其实就是 Java 对象的锁,通常会被称为“内置锁”或“对象锁”。类的对象可以有多个,所以每个对象有其独立的对象锁,互不干扰。

            monitor对象(监视器)

                  A、某一线程占有这个对象的时候,先看monitor 的计数器是不是0,如果是0还没有线程占有,这个时候线程占有这个对象,并且对这个对象的monitor+1;如果不为0,表示这个线程已经被其他线程占有,这个线程等待。当线程释放占有权的时候,monitor-1;

                  B、同一线程可以对同一对象进行多次加锁,加一次锁就monitor+1,可重入性。

      2.类锁

            synchronized(类.class) {} 修饰静态方法

            在 Java 中,针对每个类也有一个锁,可以称为“类锁”,类锁实际上是通过对象锁实现的,即类的 Class 对象锁。每个类只有一个 Class 对象,所以每个类只有一个类锁。

synchronized原理分析

1、线程堆栈分析(Jconsole、Jstack pid)

上面的程序我们启动5个线程,每个线程睡眠1分钟,我们使用Jconsole软件进行查看线程。

我们可以看到有5个线程,一个线程正在等待,其他4个线程都是阻塞状态。

使用Jstack pid查看线程:

2、JVM指令分析

对当前类进行反编译:javap -v SynchronizedTest03

找到我们写的access0access1access2access3方法:其中access0access1原理相同(锁的方法),access2access3原理相同(锁的代码块)

      A、锁的代码块(用monitor进行加锁解锁)

      【问题】为什么会有两个monitorexit?

            答:第一个是正常出口,第二个是异常出口。

      B、锁的方法(用标记进行加锁、ACC_SYNCHRONIZED)

3、使用synchronized注意的问题

(1)与moniter关联的对象不能为空

(2)synchronized作用域太大

(3)不同的monitor企图锁相同的方法

(4)多个锁的交叉导致死锁

Java虚拟机对synchronized的优化

对锁优化加入:偏向锁、轻量级锁、重量级锁(等待时间长)

每一个monitor存放在一个实例对象里面,每一个对象都和monitor进行关联,主要与对象头进行关联,关联主要根据锁的状态进行。

无锁状态:没有加锁

偏向锁在对象第一次被某一线程占有的时候,是否偏向锁置1,锁表01,写入线程号,当其他的线 程访问的时候,会去竞争,竞争失败(升级到轻量级锁)、很多次被第一次占有它的线程获取次数多--竞争成功

轻量级锁线程有交替适用,互斥性不是很强,CAS失败,00

重量级锁强互斥,10,等待时间长

自旋锁:竞争失败的时候,不是马上转化级别,而是执行几次空循环

锁消除:JIT在编译的时候吧不必要的锁去掉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Please Sit Down

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

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

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

打赏作者

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

抵扣说明:

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

余额充值