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

笔记:Java Language Specification - 章节17- 线程和锁的更多相关文章

  1. Java® Language Specification

    Java™ Platform, Standard Edition 8 API Specification http://docs.oracle.com/javase/8/docs/api/ The J ...

  2. 阅读The Java® Language Specification需要知道的英文单词

      In any case/on any account  在任何情况下 “Varargs”是“variable number of arguments”的意思.有时候也被简单的称为“variable ...

  3. 阅读The Java® Language Specification需要知道的术语

    Null Pointer Exception,简称NPE 在java中,static final修饰的是常量.根据编译器的不同行为,常量又可分为编译时常量和运行时常量. 举例说明吧 public st ...

  4. 如何从oracle官网中下载The java language specification(java 语言规范)

    第一步: 第二步: 第三步:下面这个图在这个页面的下方,所以你只要一直往下看,直到看到下图的文字为止: 第四步: 第五步: 这样你就可以成功下载该java 语言规范的pdf了. 它直接下载的网址为: ...

  5. Java 基础【07】线程同步锁的选择

    在需要线程同步的时候如何选择合适的线程锁? 例:选择可以存入到常量池当中的对象,String对象等 public class SyncTest { private String name = &quo ...

  6. Java Language and Virtual Machine Specifications

    The Java Language Specification, Java SE 8 Edition HTML | PDF The Java Virtual Machine Specification ...

  7. Java开发笔记(一百零三)线程间的通信方式

    前面介绍了多线程并发之时的资源抢占情况,以及利用同步.加锁.信号量等机制解决资源冲突问题,不过这些机制只适合同一资源的共享分配,并未涉及到某件事由的前因后果.日常生活中,经常存在两个前后关联的事务,像 ...

  8. 《深入了解java虚拟机》高效并发读书笔记——Java内存模型,线程,线程安全 与锁优化

    <深入了解java虚拟机>高效并发读书笔记--Java内存模型,线程,线程安全 与锁优化 本文主要参考<深入了解java虚拟机>高效并发章节 关于锁升级,偏向锁,轻量级锁参考& ...

  9. JAVA语言规范-线程和锁章节之同步、等待和通知

    JAVA语言规范:线程和锁 1 同步 java编程语言提供了线程间通信的多种机制.这些方法中最基本的是同步化,此方法是使用监视器实现的.JAVA中每个对象与一个监视器相关联,一个线程可以加锁和解锁监视 ...

随机推荐

  1. JDK8 Steam流操作

    原文:https://github.com/niumoo/jdk-feature/blob/master/src/main/java/net/codingme/feature/jdk8/Jdk8Str ...

  2. 201871010132-张潇潇-《面向对象程序设计(java)》第四周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  3. adb命令操作蓝牙

    打开和关闭蓝牙BT adb root adb shell svc bluetooth enable adb shell svc bluetooth disable UI层 查询:adb shell s ...

  4. Java 为什么需要包装类,如何使用包装类?

    出处:https://cloud.tencent.com/developer/article/1362754

  5. robotframework连接mysql

    1.安装mysql数据库,并启动,创建数据库test及user表(可以自定义) 2.配置robotframework环境加载DatabaseLibrary 3.安装pymysql,下载地址:https ...

  6. Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging

    1665 - Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT a ...

  7. Codeforces886(Technocup2018) F Symmetric Projections

    Codeforces886(Technocup2018) F Symmetric Projections You are given a set of n points on the plane. A ...

  8. pyinstaller 如何引入Pycharm项目中的第三方库

    使用Pycharm作为IDE的项目,引用的第三方库一般放在项目所在目录的venv\Lib\site-packages下,因此可使用以下语句引入第三方库 pyinstaller -p venv\Lib\ ...

  9. [300iq Contest 1-D]Dates

    传送门 Description 每个妹子匹配一个时间区间,每个时间最多选择\(a_i\)个妹子,每个妹子有一个快乐值,最大化总快乐值 Solution 贪心,从大往小取,能取则取 判断是否可以有完美匹 ...

  10. ACT开发初步(一)

    ACT的全称是Application Customization Toolkit,是面向ANSYS系列产品的统一的二次开发平台.利用基于Python的API(Application Programmi ...