阿里三面:让你怀疑人生的 Java 锁机制夺命连环 21 问

本文深入探讨了Java中的锁机制,包括乐观锁、悲观锁、自旋锁、可重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁等概念,详细阐述了它们的工作原理和应用场景,并通过对比分析了synchronized和Lock的区别,以及ReentrantLock的独特之处。文章适合希望提升Java并发编程能力的开发者阅读。
摘要由CSDN通过智能技术生成

前言

锁机制无处不在,锁机制是实现线程同步的基础,锁机制并不是 Java 锁独有的,其他各种计算机语言中也有着锁机制相关的实现,数据库中也有锁的相关内容,这篇文章总结的 Java 锁机制笔记希望可以帮助大家从 Java 入手,深入学习、理解 Java 中的锁机制,提升 Java 并发编程能力。

1、乐观锁

 

乐观锁是一种乐观思想,假定当前环境是读多写少,遇到并发写的概率比较低,读数据时认为别的线程不会正在进行修改(所以没有上锁)。写数据时,判断当前 与期望值是否相同,如果相同则进行更新(更新期间加锁,保证是原子性的)。

Java 中的乐观锁: CAS,比较并替换,比较当前值(主内存中的值),与预期值(当前线程中的值,主内存中值的一份拷贝)是否一样,一样则更新,否则继续进行 CAS 操作。

如上图所示,可以同时进行读操作,读的时候其他线程不能进行写操作。

2、悲观锁

 

悲观锁是一种悲观思想,即认为写多读少,遇到并发写的可能性高,每次去拿数据的时候都认为其他线程会修改,所以每次读写数据都会认为其他线程会修改,所以每次读写数据时都会上锁。其他线程想要读写这个数据时,会被这个线程 block,直到这个线程释放锁然后其他线程获取到锁。

Java 中的悲观锁: synchronized 修饰的方法和方法块、ReentrantLock。

如上图所示,只能有一个线程进行读操作或者写操作,其他线程的读写操作均不能进行。

3、自旋锁

 

自旋锁是一种技术: 为了让线程等待,我们只须让线程执行一个忙循环(自旋)。

现在绝大多数的个人电脑和服务器都是多路(核)处理器系统,如果物理机器有一个以上的处理器或者处理器核心。

能让两个或以上的线程同时并行执行,就可以让后面请求锁的那个线程 “稍等一会”,但不放弃处理器的执行时间,看看持有锁的线程是否很快就会释放锁。

自旋锁的优点: 避免了线程切换的开销。挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给 Java 虚拟机的并发性能带来了很大的压力。

自旋锁的缺点: 占用处理器的时间,如果占用的时间很长,会白白消耗处理器资源,而不会做任何有价值的工作,带来性能的浪费。因此自旋等待的时间必须有一定的限度,如果自旋超过了限定的次数仍然没有成功获得锁,就应当使用传统的方式去挂起线程。

自旋次数默认值:10 次,可以使用参数 - XX:PreBlockSpin 来自行更改。

自适应自旋: 自适应意味着自旋的时间不再是固定的,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定的。有了自适应自旋,随着程序运行时间的增长及性能监控信息的不断完善,虚拟机对程序锁的状态预测就会越来越精准。

Java 中的自旋锁: CAS 操作中的比较操作失败后的自旋等待。

4、可重入锁(递归锁)

 

可重入锁是一种技术: 任意线程在获取到锁之后能够再次获取该锁而不会被锁所阻塞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值