在互联网公司面试中,很多小伙伴都被问到过关于锁的问题 。今天,我给大家一次性把Java并发锁的全家桶彻底讲明白 。包括互斥锁、读写锁、重入锁、公平锁、悲观锁、自旋锁、偏向锁等等等等 。视频有点长,大家一定要全部看完,保证你会醍醐灌顶 。
1、锁的由来【如何理解Java中眼花缭乱的各种并发锁?】在并发编程中,经常会遇到两个以上的线程访问同一个共享变量,当同时对共享变量进行读写操作时,就会产生数据不一致的情况 。
文章插图
随着线程并发技术的发展,在多线程环境中,对线程访问资源的限制也越来越多 。为了保证资源获取的有序性和占用性,都是通过并发锁来控制的 。
2、锁的应用场景下面,我根据个人经验以及并发场景下线程的处理逻辑,总结为以下7个场景,不同场景使用不同的锁 。
1)某个线程是否锁住同步资源的情况如果要锁住同步资源则使用悲观锁,不锁住同步资源使用乐观锁 。所谓悲观锁,就是每次拿数据的时候都认为会有别人修改,所以在读数据的时候都会上锁,其他线程数据就会阻塞,直到拿到锁 。
文章插图
举个例子,假设厕所只有一个坑位,悲观锁就是上厕所会第一时间把门反锁上,这样其他人上厕所只能在门外等候,这就是阻塞 。
文章插图
而乐观锁就是开着门,当然在这个场景下一般也不会这么做 。所以,乐观锁,就是每次拿数据的时候都假设为别人不会修改,所以不会上锁;只是在更新数据的时候去判断之前有没有别的线程更新了这个数据 。如果这个数据没有被更新,当前线程将自己修改的数据成功写入 。如果数据已经被其他线程更新了,要么报错,要么自动重试 。
文章插图
乐观锁与悲观锁是一种广义上的概念,没有谁优谁劣 。乐观锁适用于写少读多的场景,因为不用上锁、释放锁,省去了锁的开销,从而提升了吞吐量 。而悲观锁适用于写多读少的场景,因为线程间竞争激励,如果使用乐观锁会导致线程不断进行重试,这样反而还降低了性能 。
2)多个线程是否共享一把锁的情况如果在并发情况下,多个线程共享一把锁就是使用共享锁,如果不能共享一把锁就是排它锁或者叫独占锁、独享锁 。共享锁是指锁可被多个线程所持有 。如果一个线程对数据加上共享锁后,那么其他线程只能对数据再加共享锁,不能加独占锁 。获得共享锁的线程只能读数据,不能修改数据 。
文章插图
在 JDK 中 ReentrantReadWriteLock 就是一种共享锁 。而独占锁是指锁一次只能被一个线程所持有 。如果一个线程对数据加上排他锁后,那么其他线程不能再对该数据加任何类型的锁 。获得独占锁的线程即能读数据又能修改数据 。
文章插图
JDK中的synchronized和J.U.C(java.util.concurrent)包中Lock的实现类都是独占锁 。另外,互斥锁是独占锁的一种常规实现,是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性 。
文章插图
互斥锁一次只能一个线程拥有互斥锁,其他线程只有等待 。而读写锁是共享锁的一种具体实现 。读写锁管理一组锁,一个是只读的锁,一个是写锁 。读锁可以在没有写锁的时候被多个线程同时持有,而写锁是独占的 。写锁的优先级要高于读锁,一个获得了读锁的线程必须能看到前一个释放的写锁所更新的内容 。读写锁相比于互斥锁并发程度更高,每次只有一个写线程,但是同时可以有多个线程并发读 。
经验总结扩展阅读
- 2023年属龙人农历十月婚嫁如何 哪天结婚吉祥
- 新qq如何快速升级qq怎么快速升级(在qq怎么快速升级等级)
- 英雄联盟怎么玩好(新人如何玩好英雄联盟)
- 如何才能玩好英雄联盟(怎么样才能玩英雄联盟最好)
- 2023测绘类专业包括哪些 就业前景如何
- 什么是 X.509 证书以及它是如何工作的?
- 华为p40pro怎么设置铃声 华为p40pro如何设置铃声
- 美团怎么修改支付方式 美团如何修改支付方式
- qq通过手机通讯录怎么添加好友 qq如何添加好友
- 微信怎么查电费明细 微信如何查电费明细