Java锁

从不同角度来说,Java中的锁分为如下类型:

偏向锁,轻量级锁,重量级锁

自旋锁

重入锁,不可重入锁

读写锁,互斥锁,独占锁,共享锁

乐观锁,悲观锁

公平锁,非公平锁

分段锁

锁膨胀

锁消除

锁粗化

分布式锁

【偏向锁】

一个线程获取到偏向锁以后,锁会记录该线程的ID,然后在没有其它线程获取该锁的情况下,该线程可以重新使用这个锁,不需要重新锁定它。

【偏向锁】的细节:

锁第一次被线程A获取的时候,JVM使用CAS的方式把线程A的ID写入锁对象的 MarkWord 中。

当线程B来争夺锁时,发现:

1、线程A已结束,或者

2、线程A未结束,但线程A不在同步块中

则线程B会把 MarkWord 设置为无锁状态,并将锁升级为【轻量级锁】。

如果线程B发现线程A未死亡且在同步块中,则线程B会忽略 MarkWord,但仍会把锁升级为【轻量级锁】。

可以看出,只要偏向锁被两个及两个以上的线程争夺,就会升级为【轻量级锁】。

偏向锁的撤销是会耗费资源的,以后版本会被弃用。

【轻量级锁】

synchronized 会使用操作系统内核态的互斥量来实现同步。这样,在线程竞争不激烈的情况下,比较消耗性能。【轻量级锁】就是来弥补这个缺陷的。

【轻量级锁】的细节:

当要执行同步块时,JVM会在栈中分配一块叫做 LockRecord 的内存,之后 JVM 会把 MarkWord 替换为 LockRecord 的指针。

如果替换成功,当前线程就获取了该锁。

没有成功的话,且不是重入,说明锁存在多线程竞争,【轻量级锁】膨胀为【重量级锁】,MarkWord 中存储的是 【重量级锁】的指针。

【重量级锁】

重量级锁是使用操作系统的互斥量(mutex)来实现的,互斥量可以处于解锁或加锁状态。

当有线程要进入同步块的时候,如果互斥量处于解锁状态,则该线程直接进入同步块;如果互斥量处于加锁状态,则该线程阻塞。

【自旋锁】

自旋其实就是循环。

当某个锁被线程A持有之后,如果同时线程B也想获取该锁,线程B不会阻塞,而是在一个死循环里不断尝试获取锁,这比直接进入阻塞状态效率要高,因为线程的恢复和挂起都需要从用户态切换到内核态。

另外,Java还引入了自适应自旋,它会根据以往的信息做参考,来决定新来的线程自旋的次数,如果不符合条件,线程会直接进入阻塞状态。

自旋锁很消耗CPU资源。

【可重入锁】

当线程已获得某带块的锁,则由该锁控制的其它同步块无需再次获得锁,就允许该线程进入。

synchronized和ReentrantLock都是可重入锁。synchronized将重入的次数记录到了栈的 LockRecored 中。ReentrantLock使用了内置变量记录重入的次数。

【不可重入锁】

线程A在获取某个锁之后,在执行其它由该锁控制的同步代码块时,不能获取到该锁导致阻塞的发生。

【读写锁】

读写锁,允许多个线程同时读取共享数据,但是一次只允许一个线程对共享数据更新。

ReentrantReadWriteLock类就是读写锁。

【独占锁】

只能被一个线程持有,synchronized和ReentrantLock都是独占锁。

【共享锁】

读写锁中的读锁是共享的,即锁可以被多个线程持有。

【互斥锁】

当一个线程持有互斥锁之后,其他线程就只能等待锁被释放才有机会去获取它。

synchronized和ReentrantLock都是互斥锁

【乐观锁】

乐观锁是一种思想,适用于读多改少的场景。

可以利用版本号+CAS操作来实现乐观锁。

为变量A添加一个版本号version,初始值为0,A可以被多个线程访问。

当有线程修改A的时候会先查看version是否为0,如果是,则允许这次修改且将0修改为1,这个操作是具有原子性的。

如果version不是0,则说明这期间有别的线程修改了变量A,这种情况由程序的设计者来决定如何进行后续的操作。

【悲观锁】

synchronized,ReentrantLock都是悲观锁。系统会悲观的认为数据总是会被修改。

【公平锁】

在公平锁中,线程会按照线程的请求顺序来获取锁。

ReentrantLock内部提供了公平锁的实现,Semaphore中也提供了公平锁的实现。

【非公平锁】

非公平锁允许线程插队。

【分段锁】

ConcurrentHashMap就采用了分段锁。

【锁膨胀】

指的是轻量级锁到重量级锁的转变。

【锁消除】

锁消除的主要判定源于逃逸分析,即堆中的数据如果不会被其他线程访问到,则会认为这些数据不会出现线程安全问题。

没有线程安全问题的数据,加锁的意义不大,可以取消代码同步。

【锁粗化】

比如一个循环里有获取锁的行为,反复进出一个同步块,这样的锁可以放到循环外面,执行整个循环可以只获取一次锁。

【分布式锁】

在电商系统中,可以使用分布式锁来防止超卖的现象。

===^^===

下面是介绍《榴芒客服系统》的博客,它是我们工作室开发的在线客服系统,欢迎下载试用:

《榴芒客服系统》https://blog.csdn.net/look4liming/article/details/164755808

相关推荐
多加点辣也没关系1 小时前
JavaScript|第31章:表单与控件
开发语言·javascript·ecmascript
菜鸟~noob2332 小时前
【电子战】 第09篇:阵列信号处理——波束形成、MVDR、MUSIC【含matlab代码】
开发语言·matlab·信号处理
ocean21032 小时前
2025-2026年Python面试高频知识点洞察
开发语言·python·面试·python八股文
零依赖极客2 小时前
Day 6·1 ARMv8.2 dotprod——vdotq_s32 一条指令做 4 个点积
c语言·开发语言·人工智能·矩阵·arm·vllm
shehuiyuelaiyuehao3 小时前
1计算机是如何工作的
java·计算机网络
letisgo54 小时前
JAVA 高级进阶07篇《@Transactional失效的8个场景:代理机制到传播行为》
java·面试·transactional·spring事务·aop动态代理
水域安全老周4 小时前
水趣钓鱼救生衣专利拆解:两级锁紧如何解决落水人衣分离
java·前端·网络
新时代牛马4 小时前
cyclictest 毛刺从哪来?从ftrace、latencytop、perf到IRQ/调度延迟定位
android·开发语言·python·kotlin
三8444 小时前
Java 模板注入(FreeMarker) · 02 · 模板引擎与 FreeMarker 语法
java·开发语言·web安全·freemarker