笔记:Java Language Specification

回答一个问题:多线程场景下,有时一个线程对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线程仍一直等待,即便对该对象锁已经空闲)
原文地址:https://www.cnblogs.com/nanlan2017/p/10319646.html