Java知识分享网 - 轻松学习从此开始!    

Java知识分享网

Java1234官方群25:java1234官方群17
Java1234官方群25:838462530
        
SpringBoot+SpringSecurity+Vue+ElementPlus权限系统实战课程 震撼发布        

最新Java全栈就业实战课程(免费)

springcloud分布式电商秒杀实战课程

IDEA永久激活

66套java实战课程无套路领取

锋哥开始收Java学员啦!

Python学习路线图

锋哥开始收Java学员啦!
当前位置: 主页 > Java文档 > Java基础相关 >

JSR133中文版 PDF 下载


分享到:
时间:2020-06-12 18:20来源:http://www.java1234.com 作者:小锋  侵权举报
JSR133中文版 PDF 下载
失效链接处理
JSR133中文版 PDF 下载

本站整理下载:
 
相关截图:
 
主要内容:


1 介绍
JavaTM 虚拟机支持多线程执行。线程是用 Thread 类来表示的。用户创建一个线程
的唯一方式是创建一个该类的对象;每个线程都与这样一个对象相关联。在对应的
Thread 对象上调用 start()方法将启动线程。
线程的行为,尤其是未正确同步时的行为,可能会让人困惑和违背直觉。本规范描
述了用 JavaTM语言编写的多线程程序的语义;包括多线程更新共享内存时,读操
作能看到什么值的规则。因为本规范与不同的硬件架构的内存模型相似,所以,这
里的语义都指的是 JavaTM 内存模型。
这些语义不会去描述多线程程序该如何执行。而是描述多线程程序允许表现出的行
为。任何执行策略,只要产生的是允许的行为,那它就是一个可接受的执行策略。
1.1 锁
有多种机制可以用于线程间通信。其中最基础的是同步,同步是用管程来实现的。
每个对象都关联着一个管程,线程可以通过它来执行锁定(lock)或解锁
(unlock)操作。每次仅有一个线程可以持有管程上的锁。其它试图锁定该管程的
线程会一直阻塞,直到能从该管程上获得锁为止。
线程 t 可以锁定一个管程多次,每个 unlock 操作都会将一次 lock 操作撤销。
synchronized 语句需要一个对象的引用;随后会尝试在该对象的管程上执行 lock 动
作,如果 lock 动作未能成功完成,将一直等待。当 lock 动作执行成功,就会运行
3 / 66
synchronized 语句块中的代码。一旦语句块中的代码执行结束,不管是正常还是异
常结束,都会在之前执行 lock 动作的那个管程上自动执行一个 unlock 动作。
synchronized 方法在调用时会自动执行一个 lock 动作。在 lock 动作成功完成之前,
都不会执行方法体。如果是实例方法,锁的是调用该方法的实例(即,方法体执行
期间的 this)相关联的管程。如果是静态方法,锁的是定义该方法的类所对应的
Class 对象。一旦方法体执行结束,不管是正常还是异常结束,都会在之前执行
lock 动作的那个管程上自动执行一个 unlock 动作。
语义既不阻止也不要求对死锁条件进行检测。程序中若线程会(直接地或间接地)
锁定多个对象,应当采取一些手段来避免死锁,若有必要,创建一些更高级别的不
会死锁的锁原语。
其它诸如读写 volatile 变量,以及 java.util.concurrent 包中的类,都为同步提供了可
选的机制。
1.2 示例中的表示法
Java 内存模型并没有完全地基于 Java 语言的面向对象特性。为了保持示例简洁明
了,通常会展示一些没有 类或方法定义或显式解引用的代码片段。大部分例子都
包含两或多个线程访问局部变量、共享全局变量或对象的实例字段。通常使用变量
名 r1 或 r2 来表示方法或线程的局部变量,这些变量不会被其它线程访问。
4 / 66
5 / 66
2 未正确同步的程序会表现出出人意料的行为
Java 的语义允许编译器和微处理器进行优化,这会影响到未正确同步的代码,可能
会使它们的行为看起来自相矛盾。
图 1:语句重排序导致的出人意料的结果
考虑图 1 中的例子。程序中用到了局部变量 r1 和 r2,以及共享变量 A 和 B。可能
会出现 r2 == 2、r1 == 1 这样的结果。直觉上,应当要么指令 1 先执行要么指令 3
先执行。如果指令 1 先执行,它不应该能看到指令 4 中写入的值。如果指令 3 先执
行,它不应该能看到指令 2 写的值。
如果某次执行表现出了这样的行为,那么我们可能得出这样的结论,指令 4 要在指
令 1 之前执行,指令 1 要在指令 2 之前执行,指令 2 要在指令 3 之前执行,指令 3
要在指令 4 之前执行。如此,从表面看来,有悖常理。
然而,从单个线程的角度看,只要重排序不会影响到该线程的执行结果,编译器就
可以对该线程中的指令进行重排序。如果指令 1 与指令 2 重排序,那就很容易看出
为什么会出现 r2 == 2 和 r1 == 1 这样的结果了。
一些编程人员可能认为程序表现出这种行为是不对的。但是,需要注意的是,这段
代码没有被充分同步:
 一个线程里有个写操作,
 另一个线程读取了这个写入的变量值,
 且读写操作没有被同步排序。
当上述情况发生时,称之为存在数据争用(data race)。当代码中存在数据争用
时,常有可能出现有违直觉的结果。
有几种机制都可以产生图 1 中的重排序。JIT 编译器和处理器可以对代码进行重新
整理。此外,运行 JVM 的机器的分级存储系统可以使代码看起来像被重排序过。
为简单起见,任何能够对代码进行重排序的东西,我们称之为编译器。源代码到字
节码的转换过程中可以重排序和改变程序,但必须是本规范允许的那些方式。
图 2 是另一个会产生出人意料的结果的例子。这个程序也没有正确同步;它里面对
共享内存访问的操作之间没有强加任何顺序。

 

------分隔线----------------------------

锋哥公众号


锋哥微信


关注公众号
【Java资料站】
回复 666
获取 
66套java
从菜鸡到大神
项目实战课程

锋哥推荐