笔记:Java Language Specification - 章节17- 线程和锁
回答一个问题:多线程场景下,有时一个线程对shared variable的修改可能对另一个线程不可见。那么,何时一个线程对内存的修改才会对另一个线程可见呢?
基本的原则: 如果 读线程 和 写线程 不进行同步,就不能保证可见性
地址:Oracle -- Java Language Specification -- Chapter 17. Threads and Locks 阐述了Java 内存模型下多线程程序的 Semantics
已经有人翻译好了: 深入分析 java 8 编程语言规范:Threads and Locks
14.19. The synchronized
Statement
注意: 每个object都有一个monitor lock,这就是内置锁。 synchronized 和 Object.wait() / Object.notify() / Object.notifyAll() 都指的是这把锁。
再明确:每把Mutex 实际上就是 1个open/closed 状态位 + 1个wait-queue (维护着排队等待这把锁而被blocked的threads)
; A mutex may either be open or closed.
; It also contains a queue of threads that are waiting for the mutex to become open
(define-datatype Mutex Mutex?
($a-mutex
(ref@closed? reference?) ; ref to bool
(ref@wait-queue reference?))) ; ref to (listof thread)
所以,obj 和 mutex 就是同义词。
一个object作为内置锁,通过 synchronized 来访问这把锁,而 执行 obj.wait() 会让本线程进入 obj的wait-queue中,obj.notify() 会“发送消息” 给该obj的 wait-queue上的所有threads,
synchronized (o) {...} === lock(o) ; {...} ; unlock(o)
o.wait() === wait(o) // 靠,面向对象的写法看起来有点怪怪的,明明语义是 让本线程去wait(o) ,写成 o.wait() 还容易让人以为是要对 o做点什么呢!
o.notify() === nofity(o)
也就是说 o 的 wait-queue 中存在3种情况的线程:
1. 因为执行 lock(o) 而被阻塞的线程。 这种线程需排队等到锁、才能进入Runnable状态被调度执行。
2. 因为 wait(o) 而加入wait-queue、等待其他线程 notify(o) 的线程,
3. 因为 wait(o, time) 而加入wait-queue、限时等待其他线程 notify(o) 的线程
wait、notify、notifyAll三者的异同: (假设有对象A,线程T)
1. 是Object类的实例方法,且是native方法
2. T调用A的这些方法时必须先拥有A的对象锁,即只能在同步方法或同步块中调用这些方法。否则会抛出IllegalMonitorStateException(是RuntimeException故无需try catch)
3. 调用wait方法并不是立马释放锁,要等同步方法或同步块执行完;
同理,调用notify、notifyAll并不会有线程立马获取到对象锁,需要等调用者所在同步方法或同步块执行完。 4. 可以理解为每个对象有个wait set(等待池)和monitor set(锁池)用来存放线程:
———— wait set中线程等待收到通知信号(notify、notifyAll)、不会竞争获取A的对象锁,
———— monitor set中的线程则竞争对象锁;
T调用A的wait方法则T进入wait set、
T调用notify或notifyAll则wait set中的一个线程(随机选)或所有线程进入monitor set竞争对象锁。
(从这可看出,第一个获得对象锁的wait线程执行完后,若没有继续调用该对象的notify或notifyAll,且monitor set中没有线程,则其他wait线程仍一直等待,即便对该对象锁已经空闲)
最新文章
- .NET DateTime 显示格式
- Git及Github入门笔记
- 行业集中度(Concentration Ratio)
- YHMMR003 农户基本信息的维护程序
- 搭建andiord sdk和安装eclipse adt插件的个人小体会
- 提取安卓手机的recovery
- Java浮点值拒绝服务漏洞危害分析
- hdu 2602 Bone Collector 背包入门题
- Docker之dockerfile
- Vim常用命令【转载】
- NYoj_49开心的小明
- HIVE扩展GIS函数
- C51学习
- Android Studio之回退Gradle版本方法
- Redmine 安装、搭建
- [Swift]LeetCode491. 递增子序列 | Increasing Subsequences
- mysql执行update语句受影响行数是0
- nginx安装配置: configure命令
- centos7.3安装Nginx
- php路由
热门文章
- 中国网络安全行业分类及全景图2019H1
- andrlid 处理大图片思路,未实践
- acwing 算法面试、笔试题公开课整理记录
- 常用dos命令(2)
- Electron实现第一个应用 ";hello world";
- 树莓派搭建基于flask的web服务器-通过移动端控制LED
- c3p0参数
- Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity (超级源点)
- Flask的响应及request属性整理
- vb.net 对字符串中的括号匹配进行判断,容许嵌套