java重点学习-线程的并发安全(2)

发布于:2024-09-18 ⋅ 阅读:(165) ⋅ 点赞:(0)

九 线程的并发安全

9.7 ReentrantLock的实现原理

  • ReentrantLock表示支持重新进入的锁,调用lock方法获取了锁之后,再次调用 lock,是不会再阻塞
  • ReentrantLock主要利用CAS+AQS队列来实现
  • 支持公平锁和非公平锁,在提供的构造器的中无参默认是非公平锁,也可以传参设置为公平锁

9.8 synchronized和Lock有什么区别?

语法层面
  • synchronized 是关键字,源码在jvm 中,用 c++语言实现
  • Lock 是接口,源码由jdk 提供,用java 语言实现
  • 使用 synchronized 时,退出同步代码块锁会自动释放,而使用 Lock 时,需要手动调用 unlock 方法释放锁
功能层面
  • 二者均属于悲观锁、都具备基本的互斥、同步、锁重入功能
  • Lock 提供了许多 synchronized 不具备的功能,例如公平锁、可打断、可超时、多条件变量
  • Lock 有适合不同场景的实现,如 ReentrantLock,ReentrantReadWriteLock(读写锁)
性能层面
  • 在没有竞争时,synchronized 做了很多优化,如偏向锁、轻量级锁,性能不赖
  • 在竞争激烈时,Lock 的实现通常会提供更好的性能

可打断

锁超时

9.9 死锁产生的条件和解决方式

1.死锁产生的条件是什么?

一个线程需要同时获取多把锁,这时就容易发生死锁

2.如何进行死锁诊断?

  • 当程序出现了死锁现象,我们可以使用jdk自带的工具:jps和jstack
  • jps:输出JVM中运行的进程状态信息
  • jstack:查看java进程内线程的堆栈信息,查看日志,检查是否有死锁如果有死锁现象,需要查看具体代码分析后,
  • 可修复可视化工具jconsole、VisualVM也可以检查死锁问题

死锁的诊断

9.10 聊-下ConcurrentHashMap

1.底层数据结构:

JDK1.7底层采用分段的数组+链表实现

JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树

2.加锁的方式

JDK1.7采用Segment分段锁,底层使用的是ReentrantLock

JDK1.8采用CAS添加新节点,采用synchronized锁定链表或红黑二叉树的首节点,相对Segment分段锁粒度更细,性能更好

9.11 导致并发程序出现问题的根本原因是什么

(Java程序中怎么保证多线程的执行安全)

  • 1.原子性synchronized、lock
  • 2.内存可见性 volatile、synchronized、lock
  • 3.有序性volatile