栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

【锁】Synchronized和lock的区别+悲观锁/乐观锁+可重入锁+闭锁+Synchronized 锁升级原理+Volatile

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【锁】Synchronized和lock的区别+悲观锁/乐观锁+可重入锁+闭锁+Synchronized 锁升级原理+Volatile

1Synchronized 和 lock的区别?

并发操作:同一时间可能有多个事务对同一数据进行读写操作

他们都是用来解决并发编程中的线程安全问题的,不同的是

1、lock是一个接口,Lock是显式锁,加锁解锁都需要我们使用java代码实现。

而synchronized是java的一个关键字。是隐式锁,加锁解锁是JVM管理的。

2、synchronized在发生异常时会自动释放占有的锁,因此不会出现死锁;

而lock发生异常时,不会主动释放占有的锁,必须手动来释放锁(finally中释放),可能引起死锁的发生。

3synchronized能锁住类、方法和代码块,而Lock是块范围内的

2什么是行锁?

行锁指的是一行数据进行加锁,行锁又分为共享锁和排他锁

共享锁:允许事务读取一行数据,允许多个事务同时获取该锁。(反正是读取,管你怎么看)

排他锁:允许事务更新和删除一行数据,具有互斥性,某个事务想要获取到锁,就必须等待其他事务释放操作该数据的锁。

3悲观锁和乐观锁?

悲观锁和乐观锁是两种思想,用于解决线程并发场景下资源竞争的问题

  • 悲观锁,每次操作数据的时候,都会认为会出现线程并发问题(会同时对数据进行修改),一开始就会进行上锁,执行完成过后才会释放锁,线程安全,性能较低,适用于写多读少的场景

  • 乐观锁,每次操作数据的时候,认为不会出现线程并发问题。不会使用加锁的形式而是在提交更新数据的时候,判断一下在操作期间有没有其他线程修改了这个数据,如果有,则重新读取,再次尝试更新(Retry),循环上述步骤直到更新成功 。否则就执行操作。线程不安全,执行效率相对较高,适用于读多写少的场景

悲观锁一般用于并发冲突概率大,对数据安全要求高的场景。【会进行加锁,不会出现线程安全问题。乐观锁在执行更新时频繁失败,需要不断重试,反而会浪费CPU资源】

乐观锁一般用于高并发,多读少写的场景【乐观锁不会进行加锁,其他线程可以进行同时访问,提高响应效率】

乐观锁的使用场景

ES是采用的乐观锁,因为ES的使用场景为读多写少,基本上不会出现线程并发问题

4什么是闭锁(CountDownLatch)?

闭锁的使用场景:多个线程执行完成之后才能执行某个方法。

5什么是可重入锁(Reentrant Lock)?

指的是某个线程已经获取到某个锁,可以再次获取锁而不会出现死锁【两个或两个以上的进程在执行过程中,因争夺系统资源而产生相互等待的现象。】。再次获取锁的同时会判断当前线程是否持有锁,如果有,就对锁的次数进行加1,释放锁的时候加了几次锁,就需要释放几次锁。

作用:可以解决多个线程对同一共享资源进行操作出现的线程并发问题,可以降低死锁问题。

在实际业务中,比如说抢购下单,在支付超时的时候,需要退抢购的库存的同时,下单成功了,就会导致超卖的问题。

所以采用可重入锁,在退库存的业务方法和下单的业务方法中都加上相同的Reentrant Lock,当一个业务方法获取到锁过后,另一个方法就需要等待当前锁的释放才能够进行执行,这样就避免了线程并发问题,导致数据不一致问题。

一个简单的锁分布式锁案例如下:

 	@Autowired
    private RedissonClient redissonClient;

    @Test
    public void testLock1(){
        RLock rLock = redissonClient.getLock("lock_stock");
        rLock.lock();	//阻塞式等待,过期时间30s
        try{
            //这里面写真正的业务,如果30秒内没有执行完当前业务,底层会有一个监控锁的看门狗会定时去检               //测,然后当当前锁进行续期,直到执行结束。这样做的好处是防止在程序执行期间锁自动过期被删除问题
//当业务执行完成不再给锁续期,即使没有手动释放锁,锁的过期时间到了也会自动释放锁
            System.out.println("加锁成功....");
            System.out.println("执行业务....");
        }finally {
            rLock.unlock();
            System.out.println("释放锁....");
        }
    }

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了,如下

 	@Test
    public void testLock2(){
    
        RLock rLock = redissonClient.getLock("lock_stock");
    	// 加锁以后10秒钟自动解锁
		// 无需调用unlock方法手动解锁
		rLock.lock(10, TimeUnit.SECONDS);
        try{
            System.out.println("加锁成功....");
            System.out.println("执行业务....");
        }finally {
            rLock.unlock();
            System.out.println("释放锁....");
        }
    }

6Synchronized 锁升级原理

        JDK1.6之前,synchronized是基于JVM内置锁实现,通过内部对象Monitor(监视器锁)实 现,监视器锁的实现依赖于底层操作系统的Mutex lock(互斥锁)实现(只有一个线程能够拿到锁,其他就需要进行等待),它是一个重量级锁性能较低,每次操作都会执行加锁。

        JDK1.6优化之后,采用锁升级的方式,就是按照1偏向锁(无锁),2轻量级锁(CAS),3重量级锁的方式来提高线程的执行效率。并不是一开始就使用重量级锁。

        锁升级主要依赖Mark World中的锁标志位。

        1在大多数情况下不会出现多线程竞争锁,而是同一个线程在多次获取锁,偏向锁的目的就是避免线程重复获取锁,降低资源开销,第一次线程获取到锁过后,会将当前线程id记录到Mark World的锁标志位中,第二次还是这个线程来获取锁时,就不需要再次获取锁,降低资源开销。

        2当有少量来争夺锁的时候,偏向锁就会升级为轻量级锁,此时竞争的线程不会阻塞,而是进行自旋。提高程序响应速度。

        3如果锁竞争严重,某个线程达到最大自旋次数(默认10次)的时候,轻量级锁会升级成重量级锁,这时候当没有获取到锁的线程,就会进行阻塞状态。

7Synchronized 加非静态和静态方法上的区别

java中synchronized的普通方法与静态方法获取的锁对象是什么_junranhuigu的博客-CSDN博客

        synchronized修饰的普通方法获取的是等效于this的指向对象的内置锁,即新创建的对象本身;

        synchronized修饰的静态方法获取的是该方法所在类的内置锁,即XXX.class

       

8Synchronized(this) 和 Synchronized (User.class) 的区别?

synchronize(this)作用于当前对象,保证同一时间只有一个线程能调用该对象。
synchronize(*.class)作用于该类所属的所有实例,保证同一时间只有一个线程能调用该类的实例。

9Synchronized 和 volatitle 关键字的区别?

这两个关键字都是用来解决并发编程中的线程安全问题的,不同点主要有以下几点

第一:volatile的实现原理,是在每次使用变量时都必须重主存中加载,修改变量后都必须立马同步到主存;synchronized的实现原理,则是锁定当前变量,让其他线程处于阻塞状态

第二:volatile只能修饰变量,synchronized用在修饰方法和同步代码块中

第三:volatile修饰的变量,不会被编译器进行指令重排序,synchronized不会限制指令重排序

第四:volatile不会造成线程阻塞,高并发时性能更高,synchronized会造成线程阻塞,高并发效率低

第五:volatile不能保证操作的原子性,因此它不能保证线程的安全,synchronized能保证操作的原子性,保证线程的安全

10一个类中两个方法中都有Synchronized(this) 请问能锁住吗?为什么

都有可能,

当创建了两个对象进行调用时,就锁不住。因为这时候this指代的是两个不同的对象,并不是同一个锁。

当创建一个对象进行调用时,就锁得住。因为这时候this指代的是当前唯一的对象,是同一把锁。

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1039006.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号