Java并发读书笔记:线程通信之等待通知机制
目录
在并发编程中,保证线程同步,从而实现线程之间正确通信,是一个值得考虑的问题。本篇将参考许多著名书籍,学习如何让多个线程之间相互配合,完成我们指定的任务。 当然本文只是学习了一部分线程间通信的方法,还有一些例如使用Lock和Condition对象,管道输入输出、生产者消费者等内容,我们之后再做学习。 synchronized 与 volatile
回顾以下synchronized的底层实现: 我们可以对下面这段代码进行反编译:
编译结果如下: 虽然同步方法和代码块的实现细节不同,但是归根结底:JVM对于方法或者代码块的实现是基于对Monitor对象的进入和退出操作。 以同步代码块举例:
下图源自《Java并发编程得艺术》4-2 新Java内存模型中提供了比锁更加轻量级的通信机制,它增强了volatile的内存语义,让volatile拥有和锁一样的语义:告知程序任何对volatile修饰变量的访问都要从共享内存中获取,对它的改变必须同步刷新回共享内存,保证了线程对变量访问的可见性。 关于volatile的重点学习,之后再做总结。 等待/通知机制等待/通知相关的方法被定义在 这些方法必须需要获取锁对象之后才能调用,也就是必须要在同步块中或同步方法中调用,否则会抛出 等待
通知
假设A和B需要获取同一把锁,A进入之后,B进入同步队列,陷入阻塞(BLOCKED)。 如果A中调用锁的wait()方法,A释放锁,并陷入等待(WAITING)。此时另外一个线程B获取的当前锁,B运行。 如果此时B中调用锁的notify()方法,A被唤醒,从等待队列转移到同步队列,只有B运行完毕了,锁被释放了,A拿到锁了,A才出来运行。 等待/通知机制依托于同步机制,确保等待线程从wait()方法返回时能够感知到通知线程对变量做出的修改。 面试常问的几个问题sleep方法和wait方法的区别sleep()和wait()方法都可以让线程放弃cpu一段时间,进入等待(WAITING)状态。 sleep()静态方法定义在Thread类中,wait()定义在Object类中。 如果线程持有某个对象的监视器,wait()调用之后,当前线程会释放锁,而sleep()则不会释放这个锁。 关于放弃对象监视器对于放弃对象监视器,wait()方法和notify()/notifyAll()有一定区别: 锁对象调用wait()方法之后,会立即释放对象监视器。而notify()/notifyAll()则不会立即释放,而是等到线程剩余代码执行完毕之后才会释放监视器。 参考书籍:《Java并发编程的艺术》 方腾飞 (编辑:北几岛) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |