具体的Thread提供的方法就不介绍了,这里会介绍线程状态,并发涉及到的相关组件以及等待通知模型
线程的状态
线程的状态需要注意等待状态与阻塞状态的区别,分别是进入等待队列和同步队列(后面会详细讲述这里的实现部分,个人理解锁的核心就是这俩队列)
synchronized关键字:保证了线程访问的可见性和排他性
正确的理解关系才能更好的理解实现。理清楚对象,监视器,同步队列,执行线程的关系才能更好的深入实现部分理解
线程获取监视器对象成功则正常访问,失败则进入同步队列
等待/通知机制
它是基于同步机制提供了等待队列的模式,其目的是为了确保等待线程从wait()方法返回时能够感知到通知线程对变量做出的修改
有以下细节需要注意
- 使用wait()、notify()和notifyAll()时需要先对调用对象加锁。
- 调用wait()方法后,线程状态由RUNNING变为WAITING,并将当前线程放置到对象的 等待队列。
- notify()或notifyAll()方法调用后,等待线程依旧不会从wait()返回,需要调用notify()或 notifAll()的线程释放锁之后,等待线程才有机会从wait()返回。
- notify()方法将等待队列中的一个等待线程从等待队列中移到同步队列中,而notifyAll() 方法则是将等待队列中所有的线程全部移到同步队列,被移动的线程状态由WAITING变为 BLOCKED。
-
从wait()方法返回的前提是获得了调用对象的锁。
WaitNotify运行过程
等待通知的经典范式
等待方遵循如下原则。
- 获取对象的锁。
- 如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件。
- 条件满足则执行对应的逻辑。
对应的伪代码如下。
synchronized(对象) {
while(条件不满足) {
对象.wait();
}
// 对应的处理逻辑
}
通知方遵循如下原则。
- 获得对象的锁。
- 改变条件。
- 通知所有等待在对象上的线程。
对应的伪代码如下。
synchronized(对象) {
// 改变条件
对象.notifyAll();
}
这个经典范式适用情况太多了
稍微改编一下就可以变为等待超时模型
synchronized(对象) {
long future = System.currentTimeMillis()+mills;
long wait = mills;
while(条件不满足 && wait>0) {
对象.wait();
wait = future - System.currentTimeMillis()();
}
// 对应的处理逻辑
}
依托于等待通知模型可以典型的构建模型有
阻塞队列(ArrayBlockedQueue(以ArrayList做中心),LinkedBlockedQueue(以LinkedList做中心))(这里还是很有价值的,下面会详细的介绍)
数据库连接池(以池对象作为中心)
线程池技术(以job队列作为中心,实际中是直接使用阻塞队列实现的)
其他
这里需要注意这个等待通知模型,它真的太屌了,后面介绍的锁的实现部分会深入的介绍等待队列,同步队列。如果没有很好的理解等待通知模型,那看实现部分感觉有点不切实际。还有WaitNotify运行过程那个图也是很好能理解等待队列,同步队列
网友评论