synchronized详解

1、synchronized 和 lock 的区别:
1、synchronized 是java中的一个关键字,而Lock是一个接口
2、synchronized 的作用域是:1、用在某一个对象上—> synchronized(this)
2、用在方法上—> public synchronized void run(){}
3、用在类上 —> synchronized(SynchronizedDemo.class){} 、 public synchronized static void method(){}
3、lock 只能给方法上锁 ***注意:Lock 要定义成static静态的全局变量,不能定义在方法里面
4、synchronized 不需要手动获取锁和释放锁,不会造成死锁 ;lock需要自己加锁和释放锁,如果没有unLock()释放锁会造成死锁;

2、synchronized 的四种状态:无锁 偏向锁 轻量锁 重量锁
如果只有A线程执行,则会变成偏向锁,单单偏向A线程。下次A线程再进来就能直接进来,不需要额外的cas操作。如果B线程进来,发现当前锁偏向A线程,就会通过cas竞争锁,竞争失败说明有多个线程竞争,就会再安全点的时候将锁升级为轻量级锁。如果轻量级锁还存在锁竞争失败的情况,就会升级为重量级锁,再竞争激烈的情况下,重量级锁会比轻量级锁更高的性能。

3、CAS算法:CAS(Compare And Swap/Set)比较并交换,CAS 算法的过程是这样:它包含 3 个参数 CAS(V,E,N)。V 表示要更新的变量(内存值),E 表示预期值(旧的),N 表示新值。当且仅当 V 值等 于 E 值时,才会将 V 的值设为 N,如果 V 值和 E 值不同,则说明已经有其他线程做了更新,则当 前线程什么都不做。最后,CAS 返回当前 V 的真实值。CAS 操作是抱着乐观的态度进行的(乐观锁),它总是认为自己可以成功完成操作。当多个线程同时 使用 CAS 操作一个变量时,只有一个会胜出,并成功更新,其余均会失败。失败的线程不会被挂 起,仅是被告知失败,并且允许再次尝试,当然也允许失败的线程放弃操作。基于这样的原理, CAS 操作即使没有锁,也可以发现其他线程对当前线程的干扰,并进行恰当的处理。

4、synchronized 和ReentrantLock相比,局限性
1、synchronized加锁的时候不能设置超时时间。ReentrantLock可以提供tryLock方法设置超时时间
2、ReentrantLock可以使用多个Condition,而synchronized却只能有1个
3、ReentrantLock可以选择公平锁和非公平锁
4、ReenTrantLock可以获得正在等待线程的个数,计数器等

5、关于synchronized与lock的性能比较
性能:在高并发的情况下都是在一个数量集的,较高和较低并发下,synchronized都比Lock来的快,基本是两倍的关系。到底是使用synchronized还是使用lock!我们写同步的时候,优先考虑synchronized,如果有特殊需要,再进一步优化,可以考虑使用lock。

synchronized使用场景1:
假设用户手速很快,极短时间内点了两次领奖按钮(前端没有进行控制,我们也不能依赖前端去控制)。那么可能掉了两次领奖接口,而且有可能第二次调用的时候查询数据库的时候,第一次领奖还没有执行完成更新领奖标记。

package com.nx.vip.p6.lock;


public class SynTest {
    public static void main(String[] args) {
        SynTest synTest = new SynTest();
        synTest.test();
    }


    public void test(){
        new SynThreadle().start();
        new SynThreadle().start();
    }
    public void syn(String userName) throws InterruptedException {
        synchronized (userName){
            System.out.println("进入到同步块"+userName);
            Thread.sleep(5000);
            System.out.println("退出同步块"+userName);
        }
    }


    class SynThreadle extends Thread{
        public void run(){
            try {
                syn("111");
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

结果:

进入到同步块111
退出同步块111
进入到同步块111
退出同步块111
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值