回答一个问题:多线程场景下,有时一个线程对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线程仍一直等待,即便对该对象锁已经空闲)

最新文章

  1. .NET DateTime 显示格式
  2. Git及Github入门笔记
  3. 行业集中度(Concentration Ratio)
  4. YHMMR003 农户基本信息的维护程序
  5. 搭建andiord sdk和安装eclipse adt插件的个人小体会
  6. 提取安卓手机的recovery
  7. Java浮点值拒绝服务漏洞危害分析
  8. hdu 2602 Bone Collector 背包入门题
  9. Docker之dockerfile
  10. Vim常用命令【转载】
  11. NYoj_49开心的小明
  12. HIVE扩展GIS函数
  13. C51学习
  14. Android Studio之回退Gradle版本方法
  15. Redmine 安装、搭建
  16. [Swift]LeetCode491. 递增子序列 | Increasing Subsequences
  17. mysql执行update语句受影响行数是0
  18. nginx安装配置: configure命令
  19. centos7.3安装Nginx
  20. php路由

热门文章

  1. 中国网络安全行业分类及全景图2019H1
  2. andrlid 处理大图片思路,未实践
  3. acwing 算法面试、笔试题公开课整理记录
  4. 常用dos命令(2)
  5. Electron实现第一个应用 "hello world"
  6. 树莓派搭建基于flask的web服务器-通过移动端控制LED
  7. c3p0参数
  8. Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity (超级源点)
  9. Flask的响应及request属性整理
  10. vb.net 对字符串中的括号匹配进行判断,容许嵌套