死磕Java——ReentrantLock
一、死磕Java——ReentrantLock
ReentrantLock
是java.util.concurrent.locks
包下一个可重入的默认是非公平的锁,ReentrantLock
类是Lock
接口的一个使用很频繁的实现类,类结构如下图:
前面说过JMM
模型要求的是可见性,原子性和有序性。解决原子性的方法也有多种,例如synchronized
同步方法或者同步代码块,也可以使用AtomicInteger
原子包装类解决,都知道synchronized
加锁是最笨重的解决方法,所里,这里使用的是ReentrantLock
加锁来实现原子性,代码如下:
class MyData {int num = 0;Lock lock = new ReentrantLock();public void add() {try {lock.lock();num++;} finally {lock.unlock();}}
}
public class ReentrantLockDemo {private static Logger log = LoggerFactory.getLogger(ReentrantLockDemo.class);public static void main(String[] args) {MyData myData = new MyData();for (int i = 1; i <= 20; i++) {new Thread(() -> {for (int j = 1; j <= 1000; j++) {myData.add();}}, String.valueOf(i)).start();}// 知道所有的线程执行结束while (Thread.activeCount() > 1) {Thread.yield();}log.info("结果:{}", myData.num);}
}
1.1.ReentrantLock的公平性
ReentrantLock
提供了一个带参数的构造函数,来让使用者决定使用是否是公平锁。
通过源码我们可以知道,无参数就是默认为非公平锁,传入true
表示公平锁,传入false
表示非公平锁,源码如下
// 空参默认为非公平锁
public ReentrantLock() {sync = new NonfairSync();}
// 根绝参数决定锁的公平性
public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();
}
1.2.ReentrantLock的非公平锁
1.2.1使用ReentrantLock加锁
// 创建一个非公平锁
Lock lock = new ReentrantLock();
try {// 加锁lock.lock();
} finally {// 释放锁lock.unlock();
}
1.2.2.执行的是ReentrantLock的lock方法
public void lock() {sync.lock();}
1.2.3.调用的是NonfairSync类的lock方法
static final class NonfairSync extends Sync {private static final long serialVersionUID = 7316153563782823691L;/*** Performs lock. Try immediate barge, backing up to normal* acquire on failure.*/final void lock() {// 通过CAS思想去AQS队列中获取将State值从0变为1,即获取到锁if (compareAndSetState(0, 1))// 获取锁成功则将当前线程标记为持有锁的线程,然后直接返回setExclusiveOwnerThread(Thread.currentThread());else// 获取锁失败则执行该方法acquire(1);}
}
1.2.4.调用AQS的cAS方法获取锁
protected final boolean compareAndSetState(int expect, int update) {// See below for intrinsics setup to support this// unsafe类是通过native方法直接操作内存数据return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
1.2.5.获取锁失败执行acquire方法
public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();
}
先看一下NonfairSync类的继承图,我们可以看见一个很重要的抽象类AbstractQueuedSynchronizer
,有关AQS
稍后在死磕,可以说AQS
是同步组件的基础。
死磕Java——ReentrantLock相关推荐
- 死磕Java并发:J.U.C之重入锁:ReentrantLock
ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机制,可以减 ...
- 死磕 java同步系列之ReentrantReadWriteLock源码解析
问题 (1)读写锁是什么? (2)读写锁具有哪些特性? (3)ReentrantReadWriteLock是怎么实现读写锁的? (4)如何使用ReentrantReadWriteLock实现高效安全的 ...
- 死磕Java并发:分析 ArrayBlockingQueue 构造函数加锁问题
作者: chenssy 来源:Java技术驿站 昨天有位小伙伴问我一个 ArrayBlockingQueue 中的一个构造函数为何需要加锁,其实这个问题我还真没有注意过.主要是在看 ArrayBloc ...
- 死磕Java并发:J.U.C之阻塞队列:ArrayBlockingQueue
作者:chenssy 来源:Java技术驿站 ArrayBlockingQueue,一个由数组实现的有界阻塞队列.该队列采用FIFO的原则对元素进行排序添加的. ArrayBlockingQueue为 ...
- 死磕Java并发:J.U.C之Java并发容器:ConcurrentLinkedQueue
作者:chenssy 来源:Java技术驿站 要实现一个线程安全的队列有两种方式:阻塞和非阻塞.阻塞队列无非就是锁的应用,而非阻塞则是CAS算法的应用.下面我们就开始一个非阻塞算法的研究:Coucur ...
- 死磕Java并发:J.U.C之并发工具类:Exchanger
作者:chenssy 来源:Java技术驿站 前面三篇博客分别介绍了CyclicBarrier.CountDownLatch.Semaphore,现在介绍并发工具类中的最后一个Exchange.Exc ...
- 死磕Java并发:J.U.C之并发工具类:CountDownLatch
作者:chenssy 来源:Java技术驿站 在上篇博客中介绍了Java四大并发工具一直的CyclicBarrier,今天要介绍的CountDownLatch与CyclicBarrier有点儿相似. ...
- 死磕Java并发:J.U.C之并发工具类:Semaphore
作者:chenssy 来源:Java技术栈公众号 信号量Semaphore是一个控制访问多个共享资源的计数器,和CountDownLatch一样,其本质上是一个"共享锁". Sem ...
- 死磕Java并发:J.U.C之并发工具类:CyclicBarrier
作者:chenssy 来源:Java技术栈公众号 CyclicBarrier,一个同步辅助类,在API中是这么介绍的: 它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier ...
最新文章
- 树莓派/香橙派自建本地DNS加速解析
- 宏观相似性与惯性质量
- PAT甲级1126 Eulerian Path:[C++题解] 欧拉路径、并查集,测试点4有问题请进来
- 机器学习入门学习笔记:(3.2)ID3决策树程序实现
- C vector详解
- 写在08年“愚人节”
- 自己总结的前端面试题
- C++ 通讯录管理系统实验报告
- android工程改包名及多工程设置
- vue自定义组件递归实现树状_一道价值25k的腾讯递归组件面试题(Vue3 + TS 实现)...
- R语言ggplot2画图3
- 安装Ubuntu镜像和VMware在安装Ubuntu镜像之后开机蓝屏的解决方案
- 华硕B85M-D台式机主板音响没反应,更新驱动还是找不到realtek高清晰音频管理器原因及解决方案
- IE浏览器F12无法使用
- Linux中对的tac命令
- 群英传内推第001期
- 叠氮PEG叠氮,N3-PEG-N3
- 教你一招快速清理DNS缓存
- 14.Yum详解,yum安装,查找,info,反向查找,组,依赖,缓存等所有操作
- 大小写英文字母对应的ASCII值
热门文章
- IT审计中应注意的几个问题(zt)
- java基础语法要学多久
- 云终端、瘦终端和胖终端三者之间有什么区别
- php万能表单源码_震撼!全网第一张源码分析全景图揭秘Nginx
- 基于Python的影视推荐系统的实现
- 人人都是极客半月刊:第 2 期
- html 得到单选按钮的值,js获取单选按钮组选择的值
- 如何用光盘映像文件重装服务器系统,韩博士教你如何使用光盘重装系统
- 出招吧!腾讯专家手敲《Redis源码日志笔记》,不服来对打!
- 隔离芯片1201,直流隔离ICoupler采用的平面磁场技术是一种全新的隔离技术(编码,内部脉冲信号,交流变压器转换)