当前位置:网站首页>【juc学习之路第7天】ReentrantLock与ReentrantReadWriteLock
【juc学习之路第7天】ReentrantLock与ReentrantReadWriteLock
2022-06-11 23:51:00 【birdyson】
线程锁
位于jucl下,主要有两种接口类型的锁:
Lock:包含以下三种形式锁的类型:
- 公平锁:不同的线程获取锁的过程是公平的
- 非公平锁:不同线程获取锁的过程是不公平的,允许竞争获取。
- 可重入锁:同一个锁可以被一个线程多次获取,避免死锁的出现。
ReadWhiteLock: 提供读锁和写锁,读时锁共享,修改时独占。
ReentrantLock
互斥锁或叫独占锁,是Lock的实现类,意思是一旦获取到锁之后,其他线程不允许再操作(无论读或写),synchronized也是互斥锁。
先观察下ReentrantLock的源码:
package java.util.concurrent.locks;
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
/** Synchronizer providing all implementation mechanics */
private final Sync sync;
}
继续扒Sync:
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
}
继续扒AbstractQueuedSynchronizer:(这就是JUC另一核心:AQS)
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer implements java.io.Serializable {
private static final long serialVersionUID = 7373984972572414691L;
}
继续:
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
AQS 的本质是一个执行队列,所有的待执行线程全部都保存在一个队列之中,可以解决死锁问题。在JUC的AQS里面提供了一个CLH队列。CLH (Craig, Landin, and Hagersten)锁是一种基于链表的可扩展、高性能、公平的自旋锁,申请线程只在本地变量上自旋,它不断轮询前驱的状态,如果发现前驱释放了锁就结束自旋。
/** JDK17 CLH Nodes */
abstract static class Node {
volatile Node prev; // initially attached via casTail
volatile Node next; // visibly nonnull when signallable
Thread waiter; // visibly nonnull when enqueued
volatile int status; // written by owner, atomic bit ops by others
}
获取锁的机制是由AQS的子类Sync提供的,Sync也有两个子类:FairSync、NonfairSync。
ReentrantLock在操作时有两种情况:
- 多个线程抢占互斥锁资源:

- 互斥锁抢夺与等待:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fShBnwgJ-1653492592222)(/Users/alexanderron/Library/Application Support/typora-user-images/image-20220525103823265.png)]](/img/44/0ba7f06287734179ee66b8f4990910.png)
等待的线程会保存在AQS中的CLH等待队列中,锁竞争的机制是由Sync决定的,可以发现默认是非公平锁,是比公平锁更有效率,也是更能发挥出计算机的性能。
private final Sync sync;
public ReentrantLock() {
sync = new NonfairSync();}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();}
lock()与unlock()
public void lock() {
// 此处简写
sync.acquire(1);
}
public void unlock() {
sync.release(1);
}
在进行线程锁定的过程之中是依靠线程锁定数量的控制,锁定的时候都会调用锁定计数的方法:acquire(1),每当一个线程被锁定了,这个时候计数就会+1,CLH就依靠锁定数量是否为0来确定是否有锁定的线程,从而解决线程死锁问题。在每一次解锁的时候会调用release(1)释放一个锁定。
设计一个抢票系统
class SaleSystem {
private int ticket;
private static final ReentrantLock LOCK = new ReentrantLock();
public SaleSystem() {
}
public SaleSystem(int ticket) {
this.ticket = ticket;
}
public void sale() {
LOCK.lock();
try {
if (this.ticket > 0) {
System.out.printf("【%s】售票成功!剩余票数:%d\n",
Thread.currentThread().getName(), this.ticket --);
} else {
System.out.printf("【%s】没有票啦!\n", Thread.currentThread().getName());
}
}catch (Exception e) {
e.printStackTrace();
} finally {
LOCK.unlock();
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
SaleSystem saleSystem = new SaleSystem(5);
for (int i = 0; i < 8; i ++) {
new Thread(saleSystem::sale).start();
}
}
}
【Thread-0】售票成功!剩余票数:5
【Thread-4】售票成功!剩余票数:4
【Thread-1】售票成功!剩余票数:3
【Thread-3】售票成功!剩余票数:2
【Thread-5】售票成功!剩余票数:1
【Thread-2】没有票啦!
【Thread-6】没有票啦!
【Thread-7】没有票啦!
ReentrantReadWriteLock
非独占锁,读锁属于共享锁,所有的读线程共享一个共享锁,当写锁工作的时候,整个共享锁将进入到暂停阶段,等待写完成后再进行多个并发并发读取。


public class ReentrantReadWriteLock
implements ReadWriteLock, java.io.Serializable {
private static final long serialVersionUID = -6992448646407690164L;
private final ReentrantReadWriteLock.ReadLock readerLock;
private final ReentrantReadWriteLock.WriteLock writerLock;
final Sync sync;
public ReentrantReadWriteLock() {
this(false);
}
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
public ReentrantReadWriteLock.WriteLock writeLock() {
return writerLock; }
public ReentrantReadWriteLock.ReadLock readLock() {
return readerLock; }
}
边栏推荐
- (interval DP | dfs+ memory) acwing 282 Stone merging
- On the knowledge points of cookie attributes and the differences between webstorage and cookies?
- Teach you to play with SSM framework
- 2022 R1 quick opening pressure vessel operation test questions and online simulation test
- oracle中dblink操作
- MySQL 8.0 decompressed version installation tutorial
- 明德扬FPGA开发板XILINX-K7核心板Kintex7 XC7K325 410T工业级
- [signals and systems] (XXII) Laplace transform and complex frequency domain analysis - s-domain analysis
- Lake Shore - supertran continuous flow cryogenic thermostat system
- The latest "capsule Network Overview" paper of imperial technology, etc., 29 pages of PDF, expounds the concept, method and application of capsule
猜你喜欢

RF中使用reuqests的两种方式

One to one correspondence of multiple schematic diagrams and PCB diagrams under Altium designer project

唤醒手腕 - 神经网络与深度学习(Tensorflow应用)更新中

SAP SD 创建/修改价格表

自定义JSP标签->概念->生命周期

Introduction aux bases de SOLR

Teach you to play with SSM framework

Acwing's first question solution attracted the first fan!!! Happy~~~

MySQL 8.0 decompressed version installation tutorial

Binary sort tree
随机推荐
Jetpack architecture component learning (3) -- activity results API usage
Mmdetection custom fetch detection result script and image_ demo. Py parsing
Summary of DOM knowledge points
sonarqube介紹和安裝步驟
【delphi】判断文件的编码方式(ANSI、Unicode、UTF8、UnicodeBIG)
swiper
CD process
I2C read / write process
VS code 编写汇编代码【微机原理】
Dom Knowledge point Summary
What is webstorage? And cookies
C collection of questions for project review
(dp) acwing 899. Edit distance
2022 high place installation, maintenance and removal of simulated examination platform for operation certificate examination question bank
Jenkins of the integrate tool
Vs code writing assembly code [microcomputer principle]
Teach you to play with SSM framework
Lake Shore—SuperTran 连续流低温恒温器系统
Lake Shore - supervaritemp low temperature thermostat
(dp+ longest common subsequence) acwing 897 Longest common subsequence