Zoey's Studio.

Java基础--多线程部分--synchronized关键字 和 wait notify

2019/05/08 Share

技术规范

代码中如何使用synchronized关键字?
synchronized关键字可以用在实例方法、静态方法和代码块上。实例方法锁定是的this,静态方法锁定的是Class对象。


synchronized关键字使用的时候需要注意什么?(方法论)
分析互斥锁要锁定的对象是什么,要保护的资源是什么,被保护资源都有什么访问路径。也要考虑原子性和可见性是否都满足。


synchronized关键字是如何保证原子性和可见性的?

  • 每个对象的对象头有一个位置会保存线程的id和该线程持有的锁数量,当其他线程尝试获得锁的时候,发现这个对象已经被别的线程锁定,就无法执行,这样保证了原子性。
  • 对一个锁的解锁 happens-before 对后续对这个锁的加锁,由于传递性原则,对共享变量操作的结果也可见于后续加锁的操作的线程,这样就保证了可见性。

synchronized的底层是如何实现的?JVM是如何优化synchronized关键字的?
待完成。


分析一个死锁的例子,为什么会出现死锁?如何避免死锁?如何查看死锁?
线程A持有a锁,想要申请b锁,线程B持有b锁,想要申请a锁,这样就出现了死锁。

因为synchronized关键字在获取不到锁的时候也不会主动释放已经持有的锁,线程A和线程B各自获取一个锁,而且线程A和线程B获取锁的顺序不是一样的,所以导致了死锁。可以有以下方式解决死锁问题

  • 使用显式锁,支持tryLock或者带限制时间的,这些方法支持在获取不到锁的时候释放已经持有的锁。
  • 线程A和线程B按照相同的顺序获取锁
  • 线程A或者线程B同时申请两把锁
    使用java自带的工具 jstack就可以查看死锁。

synchronized关键字都做了什么

  • 线程会尝试获取锁,如果失败,进入锁等待队列,状态变为BLOCKED。
  • 如果获取锁成功,执行方法,执行完毕后释放锁,并在锁等待队列中随机挑选一个线程并唤醒。

wait方法的过程
一个对象有两个队列,一个是锁等待队列,一个是条件等待队列一个线程调用了对象的wait方法后

  • 会进入该对象的条件等待队列,状态会变为WAITNG或TIME_WAITING并释放锁
  • 对象的锁等待队列中的线程会竞争锁,竞争失败的继续进入锁等待队列阻塞
    成功的线程进入方法执行,执行后如果调用了notify或notifyall方法,会把条件等待队列中的线程唤醒,移动到锁等待队列等待竞争锁
  • 一旦竞争到锁,会从wait方法中返回;如果失败,会继续进入锁等待队列中阻塞。

空循环CPU占有率高
https://blog.csdn.net/skyflying2012/article/details/50609050

CATALOG
  1. 1. 技术规范