没有合适的资源?快使用搜索试试~ 我知道了~
第15讲synchronized和ReentrantL1
需积分: 0 0 下载量 105 浏览量
2022-08-03
22:33:09
上传
评论
收藏 714KB PDF 举报
温馨提示
试读
12页
在 Java 5 以前,synchronized 是仅有的同步手段,在代码中, synchronized 可以用来修饰方法,也可以使用在特定的代码块儿上,本质上
资源详情
资源评论
资源推荐
极客时间 | Java核心技术36讲
https://time.geekbang.org/column/article/8799[2018/7/9 10:54:26]
第15
讲
| synchronized和ReentrantLock有什么区别呢?
2018-06-07 杨晓峰
第
15
讲
| synchronized
和
ReentrantLock
有什么区别呢?
朗读人:黄洲君 09′36′′ | 4.40M
从今天开始,我们将进入 Java 并发学习阶段。软件并发已经成为现代软件开发的基础能力,而
Java 精心设计的高效并发机制,正是构建大规模应用的基础之一,所以考察并发基本功也成为各个
公司面试 Java 工程师的必选项。
今天我要问你的问题是, synchronized 和 ReentrantLock 有什么区别?有人说 synchronized 最
慢,这话靠谱吗?
典型回答
synchronized 是 Java 内建的同步机制,所以也有人称其为 Intrinsic Locking,它提供了互斥的语
义和可见性,当一个线程已经获取当前锁时,其他试图获取的线程只能等待或者阻塞在那里。
在 Java 5 以前,synchronized 是仅有的同步手段,在代码中, synchronized 可以用来修饰方
法,也可以使用在特定的代码块儿上,本质上 synchronized 方法等同于把方法全部语句用
synchronized 块包起来。
ReentrantLock,通常翻译为再入锁,是 Java 5 提供的锁实现,它的语义和 synchronized 基本相
极客时间 | Java核心技术36讲
https://time.geekbang.org/column/article/8799[2018/7/9 10:54:26]
同。再入锁通过代码直接调用 lock() 方法获取,代码书写也更加灵活。与此同时,ReentrantLock
提供了很多实用的方法,能够实现很多 synchronized 无法做到的细节控制,比如可以控制
fairness,也就是公平性,或者利用定义条件等。但是,编码中也需要注意,必须要明确调用
unlock() 方法释放,不然就会一直持有该锁。
synchronized 和 ReentrantLock 的性能不能一概而论,早期版本 synchronized 在很多场景下性
能相差较大,在后续版本进行了较多改进,在低竞争场景中表现可能优于 ReentrantLock。
考点分析
今天的题目是考察并发编程的常见基础题,我给出的典型回答算是一个相对全面的总结。
对于并发编程,不同公司或者面试官面试风格也不一样,有个别大厂喜欢一直追问你相关机制的扩
展或者底层,有的喜欢从实用角度出发,所以你在准备并发编程方面需要一定的耐心。
我认为,锁作为并发的基础工具之一,你至少需要掌握:
理解什么是线程安全。
synchronized、ReentrantLock 等机制的基本使用与案例。
更近一步,你还需要:
掌握 synchronized、ReentrantLock 底层实现;理解锁膨胀、降级;理解偏斜锁、自旋锁、轻
量级锁、重量级锁等概念。
掌握并发包中 java.util.concurrent.lock 各种不同实现和案例分析。
知
识扩
展
专栏前面几期穿插了一些并发的概念,有同学反馈理解起来有点困难,尤其对一些并发相关概念比
较陌生,所以在这一讲,我也对会一些基础的概念进行补充。
首先,我们需要理解什么是线程安全。
我建议阅读 Brain Goetz 等专家撰写的《Java 并发编程实战》(Java Concurrency in
Practice),虽然可能稍显学究,但不可否认这是一本非常系统和全面的 Java 并发编程书籍。按照
其中的定义,线程安全是一个多线程环境下正确性的概念,也就是保证多线程环境下共享的、可修
改的状态的正确性,这里的状态反映在程序中其实可以看作是数据。
换个角度来看,如果状态不是共享的,或者不是可修改的,也就不存在线程安全问题,进而可以推
理出保证线程安全的两个办法:
封装:通过封装,我们可以将对象内部状态隐藏、保护起来。
极客时间 | Java核心技术36讲
https://time.geekbang.org/column/article/8799[2018/7/9 10:54:26]
不可变:还记得我们在专栏第 3 讲强调的 final 和 immutable 吗,就是这个道理,Java 语言目
前还没有真正意义上的原生不可变,但是未来也许会引入。
线程安全需要保证几个基本特性:
原子性,简单说就是相关操作不会中途被其他线程干扰,一般通过同步机制实现。
可见性,是一个线程修改了某个共享变量,其状态能够立即被其他线程知晓,通常被解释为将线
程本地状态反映到主内存上,volatile 就是负责保证可见性的。
有序性,是保证线程内串行语义,避免指令重排等。
可能有点晦涩,那么我们看看下面的代码段,分析一下原子性需求体现在哪里。这个例子通过取两
次数值然后进行对比,来模拟两次对共享状态的操作。
你可以编译并执行,可以看到,仅仅是两个线程的低度并发,就非常容易碰到 former 和 latter 不
相等的情况。这是因为,在两次取值的过程中,其他线程可能已经修改了 sharedState。
public class ThreadSafeSample {
public int sharedState;
public void nonSafeAction() {
while (sharedState < 100000) {
int former = sharedState++;
int latter = sharedState;
if (former != latter - 1) {
System.out.printf("Observed data race, former is " +
former + ", " + "latter is " + latter);
}
}
}
public static void main(String[] args) throws InterruptedException {
ThreadSafeSample sample = new ThreadSafeSample();
Thread threadA = new Thread(){
public void run(){
sample.nonSafeAction();
}
};
Thread threadB = new Thread(){
剩余11页未读,继续阅读
lirumei
- 粉丝: 67
- 资源: 301
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于matlab实现多车辆车辆路径问题,用遗传算法编程,保证可用.rar
- 基于matlab实现多层极限学习机实现手写体识别,准确率超过99%.rar
- 基于matlab实现电力系统最优潮流程序,可以应用于电力市场下的最优潮流计算 适合电力系统专业的同仁使用.rar
- 串行通信的通信协议串口协议串行通信的通信协议串口协议
- Vue构建交互式的单页面应用程序Vue构建交互式的单页面应用程序
- Spring Boot快速搭建和部署应用程序
- Redis开源的高性键值存储系统广泛应用于缓存、实时消息传递
- Qt跨平台的应用程序开发框架Qt跨平台的应用程序开发框架
- 单片机是集成处理器、存储器和输入输出设备
- 深度学习机器习方法模仿人脑神经网络深度学习机器习方法模仿人脑神经网络
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0