synchronized 原理

目录

1. synchronized 的特性

   1.1 互斥性

      1.2 可重入性

 2. synchronized 的使用

   2.1 对某个操作进行加锁

   2.2 对方法进行加锁

 3. synchronized的锁机制

   3.1 锁升级

   3.2 锁消除

   3.3 锁粗化


1. synchronized 的特性

   1.1 互斥性

     何为互斥性?

     简单来说,就是别人在用,你想用就只能等别人用完才行。

     对程序来说,当我们多个线程同时对一个锁对象进行加锁,第一个线程先完成加锁操作,第二个对象想要加锁,就必须等第一个线程将锁释放之后才能继续进行加锁操作。

      1.2 可重入性

     从字面意思来理解,就是可以多次进入,转换到代码中,就相当于同一个线程可以对一个锁对象进行多次加锁。

     关于可重入性,其实在锁的内部有 : 线程拥有者 以及 计数器

     某个线程对锁对象进行加锁,这个锁就会绑定这个线程,当这个线程重复对这个锁加锁时, 计数器就会 ++ ,解锁就会 -- , 当我们的计数器 减小到0 时候,这个锁才会彻底释放。

 

 2. synchronized 的使用

   2.1 对某个操作进行加锁
Object locker=new Object();
        synchronized(locker){
            count++;
        }

        上述我们是对 count ++ 这个操作进行加锁,当我们使用的时候,不让其他线程进行使用。

   2.2 对方法进行加锁
public class Main{
    public synchronized void Add1(int a,int b){
        
        }
    
    public void Add2(int a,int b){
            synchronized(this){
                
            }
        }

    public void Add3(int a,int b){
            synchronized(Main.class){
    
            }
        }
}

        我们在对方法进行加锁的时候,有两种加锁写法,可以直接在方法上进行加锁,也可以在方法内部对 调用该方法的对象 进行加锁 。

 3. synchronized的锁机制

   3.1 锁升级

        当我们使用 synchronized 进行加锁时, 它不是一个固定的锁状态

     当我们刚开始进行加锁时,系统并不会先 进行加锁 ,而是先做个标记 ; 当出现 锁冲突 时,锁就会自动升级成 自旋锁(轻量级锁),这时才成功上锁 ; 当锁冲突进一步加剧时,锁就会继续升级到 重量级锁 。 

     锁升级的实质,其实是 性能 与 线程安全 之间的权衡。

      

   3.2 锁消除

        这是一种编译器优化的手段。

        编译器会自动针对当前你所编写的 加锁代码,做出判断,如果这个场景下不需要加锁,编译器就会优化掉加锁这个操作。

        当然,这个操作只会在 编译器非常有把握的时候才会进行锁消除。(触发概率不算高)

   3.3 锁粗化

        锁的粒度:

        synchronized 的代码块中,代码越多,就认为 锁的粒度越大;反之,越细。

        当我们频繁的进行加锁操作,就会消耗更多的cpu资源。不如直接对整个操作进行加锁,让 锁的粒度变粗,能够并发执行的逻辑就会变得更多,也能充分利用 多核cpu资源

        实际开发过程中,使⽤细粒度锁,是期望释放锁的时候其他线程能使⽤锁.

        但是实际上可能并没有其他线程来抢占这个锁.这种情况JVM就会⾃动把锁粗化,避免频繁申请释放锁.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值