From 81cb87f454dff3f1ba1a49ec0d4083c58d893ca3 Mon Sep 17 00:00:00 2001 From: 252717 Date: Tue, 7 Mar 2017 20:44:02 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E3=80=90add=E3=80=91=201.E:\MyBlogAndCod?= =?UTF-8?q?e\BlogAndCode2\Java\Java=E7=9A=84main=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=97=AE=E9=A2=98.md=202.E:\MyBlogAndCode\Bl?= =?UTF-8?q?ogAndCode2\Java\Java=E9=87=8C=E7=9A=84=E4=BC=A0=E5=BC=95?= =?UTF-8?q?=E7=94=A8=E5=92=8C=E4=BC=A0=E5=80=BC=E7=9A=84=E5=8C=BA=E5=88=AB?= =?UTF-8?q?=E6=98=AF=E4=BB=80=E4=B9=88.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...70\345\205\263\351\227\256\351\242\230.md" | 3 +++ ...53\346\230\257\344\273\200\344\271\210.md" | 22 +++++++++++++++++++ Java/README.md | 5 ++++- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 "Java/Java\347\232\204main\346\226\271\346\263\225\347\233\270\345\205\263\351\227\256\351\242\230.md" create mode 100644 "Java/Java\351\207\214\347\232\204\344\274\240\345\274\225\347\224\250\345\222\214\344\274\240\345\200\274\347\232\204\345\214\272\345\210\253\346\230\257\344\273\200\344\271\210.md" diff --git "a/Java/Java\347\232\204main\346\226\271\346\263\225\347\233\270\345\205\263\351\227\256\351\242\230.md" "b/Java/Java\347\232\204main\346\226\271\346\263\225\347\233\270\345\205\263\351\227\256\351\242\230.md" new file mode 100644 index 0000000..6704255 --- /dev/null +++ "b/Java/Java\347\232\204main\346\226\271\346\263\225\347\233\270\345\205\263\351\227\256\351\242\230.md" @@ -0,0 +1,3 @@ +# Java的main方法相关问题 +* 如果`main`方法被声明为`private`会怎么样? + 如果是在`IDE`中运行,比如`Eclipse`中连`Java Application`按钮都没有,所以能通过编译但是不能运行,在命令行中运行应该是会提示`main`方法不是`public`. diff --git "a/Java/Java\351\207\214\347\232\204\344\274\240\345\274\225\347\224\250\345\222\214\344\274\240\345\200\274\347\232\204\345\214\272\345\210\253\346\230\257\344\273\200\344\271\210.md" "b/Java/Java\351\207\214\347\232\204\344\274\240\345\274\225\347\224\250\345\222\214\344\274\240\345\200\274\347\232\204\345\214\272\345\210\253\346\230\257\344\273\200\344\271\210.md" new file mode 100644 index 0000000..a8e7e56 --- /dev/null +++ "b/Java/Java\351\207\214\347\232\204\344\274\240\345\274\225\347\224\250\345\222\214\344\274\240\345\200\274\347\232\204\345\214\272\345\210\253\346\230\257\344\273\200\344\271\210.md" @@ -0,0 +1,22 @@ +# Java里的传引用和传值的区别是什么 +## 基本概念 +* 传值 +传值就是指将一个值传递到方法的内部。例如`int a = 5`,那么也就是给`int`型变量`a`赋值,值为`5`.如果一个方法,将这个变量传进方法的内部,则进行的就是传值。在`Java`中,有`8`种基本数据类型,它们分别为:`int、long、float、double、char、boolean、short、byte`.这`8`种基本的数据类型作为参数进行传递是,都是进行的传值。·除此之外,还有一种特殊的情况,`String`。本身`String`是一个引用类型,很多人认为在向方法中传递`String`类型参数时,是进行传引用。其实在这里,`String`可以看做为一个包装类,因为`String`其本身就是通过字符数组实现的,那么它在实现参数传递的时候,也就是以`char`型数据的方式进行的,也就是进行传值。 +* 传引用 +`java`中的引用可以初步的理解为地址。也是在`new`了一个对象后,该对象是存在`JVM`的`Heap`区,也就是堆。那么必然有一个地址要指向这个对象的在`JVM`中的位置,那么,指向这个对象的这个地址就可以简单的理解为“引用”。 + +## 实践 +`Java`确实使用对象的引用来做计算的,所有的对象变量都是引用。但是,`Java`在向方法传递参数时传的不是引用,是值。 +以 `swap()` 函数为例: +``` +public void swap(int var1, int var2) +{ + int temp = var1; + var1 = var2; + var2 = temp; +} +``` +当`swap`方法返回时,被当作参数传入的变量仍然保持了原来的值不变。如果我们把传入的`int`型变量改为`Object`型也是一样的,因为`Java`通过传值来传递引用的。 + +## 原因分析 +`Java`复制并传递了“引用”的值,而不是对象。因此,方法中对对象的计算是会起作用的,因为引用指向了原来的对象。但是因为方法中对象的引用是“副本”,所以对象交换就没起作用。交换动作只对方法中的引用副本起作用了,不影响方法外的引用。所以不好意思,方法被调用后,改变不了方法外的对象的引用。如果要对方法外的对象引用做交换,我们应该交换原始的引用,而不是它的副本。 diff --git a/Java/README.md b/Java/README.md index 3e1c4b1..ddd1405 100644 --- a/Java/README.md +++ b/Java/README.md @@ -1,2 +1,5 @@ # Java -* Java多线程之内存可见性 +* `Java`多线程之内存可见性 +* `Java`里的传引用和传值的区别是什么 +* `ArrayList`的`toArray`方法 +* `Java`的`main`方法相关问题 From 71b30b6e2d82ad885ad595dc4de42ef39cc49009 Mon Sep 17 00:00:00 2001 From: luohao Date: Wed, 8 Mar 2017 21:45:06 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=EF=BC=BBupdate=EF=BC=BDJava/README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Java/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Java/README.md b/Java/README.md index ddd1405..be4975c 100644 --- a/Java/README.md +++ b/Java/README.md @@ -3,3 +3,4 @@ * `Java`里的传引用和传值的区别是什么 * `ArrayList`的`toArray`方法 * `Java`的`main`方法相关问题 +* `Java`中的`equals`和`==`浅析 From f21fb7fc842173a541c55e18c83f0b7946cdf56d Mon Sep 17 00:00:00 2001 From: luohao Date: Wed, 8 Mar 2017 21:45:21 +0800 Subject: [PATCH 03/11] =?UTF-8?q?=EF=BC=BBadd=EF=BC=BD=20Java/`Java`?= =?UTF-8?q?=E4=B8=AD=E7=9A=84`equals`=E5=92=8C`=3D=3D`=E6=B5=85=E6=9E=90.m?= =?UTF-8?q?d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...45\222\214`==`\346\265\205\346\236\220.md" | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 "Java/`Java`\344\270\255\347\232\204`equals`\345\222\214`==`\346\265\205\346\236\220.md" diff --git "a/Java/`Java`\344\270\255\347\232\204`equals`\345\222\214`==`\346\265\205\346\236\220.md" "b/Java/`Java`\344\270\255\347\232\204`equals`\345\222\214`==`\346\265\205\346\236\220.md" new file mode 100644 index 0000000..e6454b6 --- /dev/null +++ "b/Java/`Java`\344\270\255\347\232\204`equals`\345\222\214`==`\346\265\205\346\236\220.md" @@ -0,0 +1,149 @@ +# `Java`中的`equals`和`==`浅析 +先看一段`Java`代码: +``` +package test; + +public class HelloWorld { + public static void main(String[] args) { + String str1 = new String("hello"); + String str2 = new String("hello"); + + System.out.println(str1==str2); + System.out.println(str1.equals(str2)); + } +} +``` +输出结果: +``` +false +true +``` +输出结果不一样?==和equals方法之间的区别是什么? + +## 关系操作符“==”到底比较的是什么? +`eg`: +``` +public class Main { + + /** + * @param args + */ + public static void main(String[] args) { + // TODO Auto-generated method stub + + int n=3; + int m=3; + + System.out.println(n==m); + + String str = new String("hello"); + String str1 = new String("hello"); + String str2 = new String("hello"); + + System.out.println(str1==str2); + + str1 = str; + str2 = str; + System.out.println(str1==str2); + } + +} +``` +输出结果为 `true false true` + +`n==m`结果为`true`,这个很容易理解,变量`n`和变量`m`存储的值都为`3`,肯定是相等的。而为什么`str1`和`str2`两次比较的结果不同?要理解这个其实只需要理解基本数据类型变量和非基本数据类型变量的区别。 + +在`Java`中游`8`种基本数据类型: + +  浮点型:`float(4 byte), double(8 byte)`` + +  整型:`byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)`` + +  字符型: `char(2 byte)`` + +  布尔型: `boolean`(`JVM`规范没有明确规定其所占的空间大小,仅规定其只能够取字面值`"true"`和`"false"`) + +对于这`8`种基本数据类型的变量,变量直接存储的是“值”,因此在用关系操作符==来进行比较时,比较的就是 “值” 本身。要注意浮点型和整型都是有符号类型的,而`char`是无符号类型的(`char`类型取值范围为`0~2^16-1`). + +也就是说比如: +``` +  int n=3; + +  int m=3;  +``` +变量`n`和变量`m`都是直接存储的`"3"`这个数值,所以用`==`比较的时候结果是`true`。 + +而对于非基本数据类型的变量,在一些书籍中称作为 引用类型的变量。比如上面的`str1`就是引用类型的变量,引用类型的变量存储的并不是 “值”本身,而是于其关联的对象在内存中的地址。比如下面这行代码: +``` +  String str1; +``` + +这句话声明了一个引用类型的变量,此时它并没有和任何对象关联。 + +而通过`new String("hello")`来产生一个对象(也称作为类`String`的一个实例),并将这个对象和`str1`进行绑定: +``` +  str1= new String("hello"); +``` +那么`str1`指向了一个对象(很多地方也把`str1`称作为对象的引用),此时变量`str1`中存储的是它指向的对象在内存中的存储地址,并不是“值”本身,也就是说并不是直接存储的字符串`"hello"`。这里面的引用和`C/C++`的指针很类似。 + +因此在用`==`对`str1`和`str2`进行第一次比较时,得到的结果是`false`。因此它们分别指向的是不同的对象,也就是说它们实际存储的内存地址不同。 + +而在第二次比较时,都让`str1`和`str2`指向了`str`指向的对象,那么得到的结果毫无疑问是`true`。 +## equals比较的又是什么? +`equals`方法是基类`Object`中的方法,因此对于所有的继承于`Object`的类都会有该方法。为了更直观地理解`equals`方法的作用,直接看`Object`类中`equals`方法的实现。 +源码: +``` +public boolean equals(Object obj) { + return (this == obj); +} +``` +很显然,在`Object`类中,`equals`方法是用来比较两个对象的引用是否相等,即是否指向同一个对象。 + +但是有些朋友又会有疑问了,为什么下面一段代码的输出结果是`true`? +``` +String str1 = new String("hello"); +String str2 = new String("hello"); +System.out.println(str1.equals(str2)); +``` +要知道究竟,可以看一下`String`类的`equals`方法的具体实现,同样在该路径下,`String.java`为`String`类的实现。 + +下面是`String`类中`equals`方法的具体实现: +``` +public boolean equals(Object anObject) { + if (this == anObject) { + return true; + } + if (anObject instanceof String) { + String anotherString = (String)anObject; + int n = value.length; + if (n == anotherString.value.length) { + char v1[] = value; + char v2[] = anotherString.value; + int i = 0; + while (n-- != 0) { + if (v1[i] != v2[i]) + return false; + i++; + } + return true; + } + } + return false; +} +``` +可以看出,`String`类对`equals`方法进行了重写,用来比较指向的字符串对象所存储的字符串是否相等。 + +## 总结 +其他的一些类诸如`Double,Date,Integer`等,都对`equals`方法进行了重写用来比较指向的对象所存储的内容是否相等。 + +  总结来说: + +  1)对于`==`,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等; + +    如果作用于引用类型的变量,则比较的是所指向的对象的地址 + +  2)对于`equals`方法,注意:`equals`方法不能作用于基本数据类型的变量 + +    如果没有对`equals`方法进行重写,则比较的是引用类型的变量所指向的对象的地址; + +    诸如`String、Date`等类对`equals`方法进行了重写的话,比较的是所指向的对象的内容。 From a636dc2f8a9169832d41de150cd9840a3cef9a32 Mon Sep 17 00:00:00 2001 From: luohao Date: Wed, 8 Mar 2017 22:41:43 +0800 Subject: [PATCH 04/11] [update] Java/README.md --- Java/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Java/README.md b/Java/README.md index be4975c..bd9c56b 100644 --- a/Java/README.md +++ b/Java/README.md @@ -4,3 +4,4 @@ * `ArrayList`的`toArray`方法 * `Java`的`main`方法相关问题 * `Java`中的`equals`和`==`浅析 +* `equals()`与`hashCode()`方法浅析 From 2b17d40b6f3cfaba2a589d4cf2b2e5f5e7f567d7 Mon Sep 17 00:00:00 2001 From: luohao Date: Wed, 8 Mar 2017 22:41:58 +0800 Subject: [PATCH 05/11] =?UTF-8?q?[add]=20Java/equals()=E4=B8=8EhashCode()?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E6=B5=85=E6=9E=90.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...71\346\263\225\346\265\205\346\236\220.md" | 294 ++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 "Java/equals()\344\270\216hashCode()\346\226\271\346\263\225\346\265\205\346\236\220.md" diff --git "a/Java/equals()\344\270\216hashCode()\346\226\271\346\263\225\346\265\205\346\236\220.md" "b/Java/equals()\344\270\216hashCode()\346\226\271\346\263\225\346\265\205\346\236\220.md" new file mode 100644 index 0000000..d908385 --- /dev/null +++ "b/Java/equals()\344\270\216hashCode()\346\226\271\346\263\225\346\265\205\346\236\220.md" @@ -0,0 +1,294 @@ +# `equals()`与`hashCode()`方法浅析 + +## 前提 +`java.lang.Object`类中有两个非常重要的方法: +* ```public boolean equals(Object obj)``` +* ```public int hashCode()``` + +`Object`类是类继承结构的基础,所以是每一个类的父类。所有的对象,包括数组,都实现了在`Object`类中定义的方法。 + +## `equals()`方法详解 + +`equals()`方法是用来判断其他的对象是否和该对象相等. + +`equals()`方法在`object`类中定义如下: +``` +public boolean equals(Object obj) { + return (this == obj); +} +``` +很明显是对两个对象的地址值进行的比较(即比较引用是否相同)。但是我们知道,`String 、Math、Integer、Double`等这些封装类在使用`equals()`方法时,已经覆盖了`object`类的`equals()`方法。 + +比如在`String`类中如下: +``` +public boolean equals(Object anObject) { + if (this == anObject) { + return true; + } + if (anObject instanceof String) { + String anotherString = (String)anObject; + int n = count; + if (n == anotherString.count) { + char v1[] = value; + char v2[] = anotherString.value; + int i = offset; + int j = anotherString.offset; + while (n– != 0) { + if (v1[i++] != v2[j++]) + return false; + } + return true; + } + } + return false; +} +``` + +很明显,这是进行的内容比较,而已经不再是地址的比较。依次类推`Math、Integer、Double`等这些类都是重写了`equals()`方法的,从而进行的是内容的比较。当然,基本类型是进行值的比较。 + +它的性质有: + +* 自反性(`reflexive`)。对于任意不为`null`的引用值`x`,`x.equals(x)`一定是`true`。 + +* 对称性(`symmetric`)。对于任意不为`null`的引用值`x`和`y`,当且仅当`x.equals(y)`是`true`时,`y.equals(x)`也是`true`。 + +* 传递性(`transitive`)。对于任意不为`null`的引用值`x`、`y`和`z`,如果`x.equals(y)`是`true`,同时`y.equals(z)`是`true`,那么`x.equals(z)`一定是`true`。 + +* 一致性(`consistent`)。对于任意不为`null`的引用值`x`和`y`,如果用于`equals`比较的对象信息没有被修改的话,多次调用时`x.equals(y)`要么一致地返回`true`要么一致地返回`false`。 + +对于任意不为`null`的引用值`x,x.equals(null)`返回`false`。 + +对于`Object`类来说,`equals()`方法在对象上实现的是差别可能性最大的等价关系,即,对于任意非`null`的引用值`x`和`y`,当且仅当`x`和`y`引用的是同一个对象,该方法才会返回`true`。 + +需要注意的是当`equals()`方法被`override`时,`hashCode()`也要被`override`。按照一般`hashCode()`方法的实现来说,相等的对象,它们的`hash code`一定相等。 + +## `hashcode()` 方法详解 +`hashCode()`方法给对象返回一个`hash code`值。这个方法被用于`hash tables`,例如H`ashMap`。 + +它的性质是: + +在一个`Java`应用的执行期间,如果一个对象提供给`equals`做比较的信息没有被修改的话,该对象多次调用`hashCode()`方法,该方法必须始终如一返回同一个`integer`。 + +如果两个对象根据`equals(Object)`方法是相等的,那么调用二者各自的`hashCode()`方法必须产生同一个`integer`结果。 + +并不要求根据`equals(java.lang.Object)`方法不相等的两个对象,调用二者各自的`hashCode()`方法必须产生不同的`integer`结果。然而,程序员应该意识到对于不同的对象产生不同的`integer`结果,有可能会提高`hash table`的性能。 + +大量的实践表明,由`Object`类定义的`hashCode()`方法对于不同的对象返回不同的`integer`。 + +在`object`类中,`hashCode`定义如下: +``` +public native int hashCode(); +``` + 说明是一个本地方法,它的实现是根据本地机器相关的。当然我们可以在自己写的类中覆盖`hashcode()`方法,比如`String、Integer、Double`等这些类都是覆盖了`hashcode()`方法的。例如在`String`类中定义的`hashcode()`方法如下: + ``` + public int hashCode() { + int h = hash; + if (h == 0) { + int off = offset; + char val[] = value; + int len = count; + + for (int i = 0; i < len; i++) { + h = 31 * h + val[off++]; + } + hash = h; + } + return h; +} + ``` +解释一下这个程序(`String`的`API`中写到):`s[0]* 31^(n-1) + s[1] * 31^(n-2) + … + s[n-1]`使用 `int` 算法,这里 `s[i]` 是字符串的第 `i` 个字符,`n` 是字符串的长度,`^` 表示求幂(空字符串的哈希码为 `0`)。 + +想要弄明白`hashCode`的作用,必须要先知道`Java`中的集合。   +总的来说,`Java`中的集合(`Collection`)有两类,一类是`List`,再有一类是`Set`。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。这里就引出一个问题:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢? + +这就是`Object.equals`方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有`1000`个元素,那么第`1001`个元素加入集合时,它就要调用`1000`次`equals`方法。这显然会大大降低效率。 + +于是,`Java`采用了哈希表的原理。哈希(`Hash`)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上,初学者可以简单理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。 + +这样一来,当集合要添加新的元素时,先调用这个元素的`hashCode`方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的`equals`方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用`equals`方法的次数就大大降低了,几乎只需要一两次。 + +简而言之,在集合查找时,`hashcode`能大大降低对象比较次数,提高查找效率! + +`Java`对象的`eqauls`方法和`hashCode`方法是这样规定的: + + * 1、相等(相同)的对象必须具有相等的哈希码(或者散列码)。 + + * 2、如果两个对象的hashCode相同,它们并不一定相同。 + +以下是`Object`对象`API`关于`equal`方法和`hashCode`方法的说明: + + `If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result. + It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.` + +以上`API`说明是对之前`2`点的官方详细说明 +关于第一点,相等(相同)的对象必须具有相等的哈希码(或者散列码),为什么? + +想象一下,假如两个`Java`对象`A`和`B`,`A`和`B`相等(`eqauls`结果为`true`),但`A`和`B`的哈希码不同,则`A`和`B`存入`HashMap`时的哈希码计算得到的`HashMap`内部数组位置索引可能不同,那么`A`和`B`很有可能允许同时存入`HashMap`,显然相等`/`相同的元素是不允许同时存入`HashMap`,`HashMap`不允许存放重复元素。 + +关于第二点,两个对象的`hashCode`相同,它们并不一定相同 + +也就是说,不同对象的`hashCode`可能相同;假如两个`Java`对象`A`和`B`,`A`和`B`不相等(`eqauls`结果为`false`),但`A`和`B`的哈希码相等,将`A`和`B`都存入`HashMap`时会发生哈希冲突,也就是`A`和`B`存放在`HashMap`内部数组的位置索引相同这时`HashMap`会在该位置建立一个链接表,将`A`和`B`串起来放在该位置,显然,该情况不违反`HashMap`的使用原则,是允许的。当然,哈希冲突越少越好,尽量采用好的哈希算法以避免哈希冲突。 + +所以,`Java`对于`eqauls`方法和`hashCode`方法是这样规定的: +* 1.如果两个对象相同,那么它们的`hashCode`值一定要相同; +* 2.如果两个对象的`hashCode`相同,它们并不一定相同(这里说的对象相同指的是用`eqauls`方法比较)。如不按要求去做了,会发现相同的对象可以出现在`Set`集合中,同时,增加新元素的效率会大大下降。 +* 3.`equals()`相等的两个对象,`hashcode()`一定相等;`equals()`不相等的两个对象,却并不能证明他们的`hashcode()`不相等。 + +换句话说,`equals()`方法不相等的两个对象,`hashcode()`有可能相等(我的理解是由于哈希码在生成的时候产生冲突造成的)。反过来,`hashcode()`不等,一定能推出`equals()`也不等;`hashcode()`相等,`equals()`可能相等,也可能不等。 + +在`object`类中,`hashcode()`方法是本地方法,返回的是对象的地址值,而`object`类中的e`quals()`方法比较的也是两个对象的地址值,如果`equals()`相等,说明两个对象地址值也相等,当然`hashcode()`也就相等了;在`String`类中,`equals()`返回的是两个对象内容的比较,当两个对象内容相等时,H`ashcode()`方法根据`String`类的重写代码的分析,也可知道`hashcode()`返回结果也会相等。以此类推,可以知道`Integer、Double`等封装类中经过重写的`equals()`和`hashcode()`方法也同样适合于这个原则。当然没有经过重写的类,在继承了`object`类的`equals()`和`hashcode()`方法后,也会遵守这个原则。 + +## `Hashset、Hashmap、Hashtable与hashcode()`和`equals()`的密切关系 +`Hashset`是继承`Set`接口,`Set`接口又实现`Collection`接口,这是层次关系。那么`Hashset、Hashmap、Hashtable`中的存储操作是根据什么原理来存取对象的呢? + +下面以`HashSet`为例进行分析,我们都知道:在`hashset`中不允许出现重复对象,元素的位置也是不确定的。在`hashset`中又是怎样判定元素是否重复的呢?在`java`的集合中,判断两个对象是否相等的规则是: +* 1.判断两个对象的`hashCode`是否相等 + 如果不相等,认为两个对象也不相等,完毕 + 如果相等,转入`2` + (这一点只是为了提高存储效率而要求的,其实理论上没有也可以,但如果没有,实际使用时效率会大 大降低,所以我们这里将其做为必需的。) + +* 2.判断两个对象用`equals`运算是否相等 + 如果不相等,认为两个对象也不相等 + 如果相等,认为两个对象相等(`equals()`是判断两个对象是否相等的关键) + 为什么是两条准则,难道用第一条不行吗?不行,因为前面已经说了,`hashcode()`相等时,`equals()`方法也可能不等,所以必须用第`2`条准则进行限制,才能保证加入的为非重复元素。 + +例1: +``` +package com.bijian.study; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +public class HashSetTest { + + public static void main(String args[]) { + String s1 = new String("aaa"); + String s2 = new String("aaa"); + System.out.println(s1 == s2); + System.out.println(s1.equals(s2)); + System.out.println(s1.hashCode()); + System.out.println(s2.hashCode()); + Set hashset = new HashSet(); + hashset.add(s1); + hashset.add(s2); + Iterator it = hashset.iterator(); + while (it.hasNext()) { + System.out.println(it.next()); + } + } +} +``` +运行结果: +``` +false +true +96321 +96321 +aaa +``` +这是因为`String`类已经重写了`equals()`方法和`hashcode()`方法,所以`hashset`认为它们是相等的对象,进行了重复添加。 +例2: +``` +package com.bijian.study; + +import java.util.HashSet; +import java.util.Iterator; + +public class HashSetTest { + + public static void main(String[] args) { + HashSet hs = new HashSet(); + hs.add(new Student(1, "zhangsan")); + hs.add(new Student(2, "lisi")); + hs.add(new Student(3, "wangwu")); + hs.add(new Student(1, "zhangsan")); + + Iterator it = hs.iterator(); + while (it.hasNext()) { + System.out.println(it.next()); + } + } +} + +class Student { + int num; + String name; + + Student(int num, String name) { + this.num = num; + this.name = name; + } + + public String toString() { + return num + ":" + name; + } +} +``` +运行结果: +``` +zhangsan +wangwu +lisi +zhangsan +``` +为什么`hashset`添加了相等的元素呢,这是不是和`hashset`的原则违背了呢?回答是:没有。因为在根据`hashcode()`对两次建立的`new Student(1,“zhangsan”)`对象进行比较时,生成的是不同的哈希码值,所以`hashset`把他当作不同的对象对待了,当然此时的`equals()`方法返回的值也不等。 + +为什么会生成不同的哈希码值呢?上面我们在比较`s1`和`s2`的时候不是生成了同样的哈希码吗?原因就在于我们自己写的`Student`类并没有重新自己的`hashcode()`和`equals()`方法,所以在比较时,是继承的`object`类中的`hashcode()`方法,而`object`类中的`hashcode()`方法是一个本地方法,比较的是对象的地址(引用地址),使用`new`方法创建对象,两次生成的当然是不同的对象了,造成的结果就是两个对象的`hashcode()`返回的值不一样,所以`Hashset`会把它们当作不同的对象对待。 + +怎么解决这个问题呢?答案是:在`Student`类中重新`hashcode()`和`equals()`方法。 +``` +class Student { + int num; + String name; + + Student(int num, String name) { + this.num = num; + this.name = name; + } + + public int hashCode() { + return num * name.hashCode(); + } + + public boolean equals(Object o) { + Student s = (Student) o; + return num == s.num && name.equals(s.name); + } + + public String toString() { + return num + ":" + name; + } +} +``` +运行结果: +``` +1:zhangsan +3:wangwu +2:lisi +``` +可以看到重复元素的问题已经消除,根据重写的方法,即便两次调用了`new Student(1,"zhangsan")`,我们在获得对象的哈希码时,根据重写的方法`hashcode()`,获得的哈希码肯定是一样的,当然根据`equals()`方法我们也可判断是相同的,所以在向h`ashset`集合中添加时把它们当作重复元素看待了。 + +重写`equals()`和`hashcode()`小结: + +* 1.重点是`equals`,重写`hashCode`只是技术要求(为了提高效率) +* 2.为什么要重写`equals`呢?因为在`java`的集合框架中,是通过`equals`来判断两个对象是否相等的 +* 3.在`hibernate`中,经常使用`set`集合来保存相关对象,而`set`集合是不允许重复的。在向`HashSet`集合中添加元素时,其实只要重写`equals()`这一条也可以。但当`hashset`中元素比较多时,或者是重写的`equals()`方法比较复杂时,我们只用e`quals()`方法进行比较判断,效率也会非常低,所以引入了h`ashCode()`这个方法,只是为了提高效率,且这是非常有必要的。比如可以这样写: +``` +public int hashCode(){ + return 1; //等价于hashcode无效 +} +``` +这样做的效果就是在比较哈希码的时候不能进行判断,因为每个对象返回的哈希码都是`1`,每次都必须要经过比较`equals()`方法后才能进行判断是否重复,这当然会引起效率的大大降低。 + + + +## 文章参考: + +[在Java中正确地使用equals()和hashCode()方法](http://boxingp.github.io/blog/2015/02/24/use-equals-and-hashcode-methods-in-java-correctly/) + +[Java中equals()与hashCode()方法详解](http://bijian1013.iteye.com/blog/1972404) + +[深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用](http://kakajw.iteye.com/blog/935226) + +[Java hashCode() 和 equals()的若干问题解答](http://www.cnblogs.com/skywang12345/p/3324958.html) From b9e3b0c89c07f25222ddb4686d5ff2ab3bbee43d Mon Sep 17 00:00:00 2001 From: luohao Date: Wed, 8 Mar 2017 23:04:23 +0800 Subject: [PATCH 06/11] =?UTF-8?q?[update]=201Java/Java=E7=9A=84main?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E7=9B=B8=E5=85=B3=E9=97=AE=E9=A2=98.md=202.J?= =?UTF-8?q?ava/README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...225\347\233\270\345\205\263\351\227\256\351\242\230.md" | 7 +++++++ Java/README.md | 2 ++ 2 files changed, 9 insertions(+) diff --git "a/Java/Java\347\232\204main\346\226\271\346\263\225\347\233\270\345\205\263\351\227\256\351\242\230.md" "b/Java/Java\347\232\204main\346\226\271\346\263\225\347\233\270\345\205\263\351\227\256\351\242\230.md" index 6704255..d755df3 100644 --- "a/Java/Java\347\232\204main\346\226\271\346\263\225\347\233\270\345\205\263\351\227\256\351\242\230.md" +++ "b/Java/Java\347\232\204main\346\226\271\346\263\225\347\233\270\345\205\263\351\227\256\351\242\230.md" @@ -1,3 +1,10 @@ # Java的main方法相关问题 * 如果`main`方法被声明为`private`会怎么样? 如果是在`IDE`中运行,比如`Eclipse`中连`Java Application`按钮都没有,所以能通过编译但是不能运行,在命令行中运行应该是会提示`main`方法不是`public`. +* 说明一下`public static void main(String args[])`这段声明里每个关键字的作用 + `public`: `main`方法是`Java`程序运行时调用的第一个方法,因此它必须对`Java`环境可见。所以可见性设置为`public`. + `static`: `Java`平台调用这个方法时不会创建这个类的一个实例,因此这个方法必须声明为`static`。 + `void`: `main`方法没有返回值。 + `String`是命令行传进参数的类型,`args`是指命令行传进的字符串数组。 +* 如果去掉了`main`方法的`static`修饰符会怎样? + 程序能正常编译。运行时会抛NoSuchMethodError异常。 diff --git a/Java/README.md b/Java/README.md index bd9c56b..07fe480 100644 --- a/Java/README.md +++ b/Java/README.md @@ -5,3 +5,5 @@ * `Java`的`main`方法相关问题 * `Java`中的`equals`和`==`浅析 * `equals()`与`hashCode()`方法浅析 +* `Java`的”一次编写,处处运行”是如何实现的 +* 静态类型有什么特点? From 8d569e8e0960721fb44ab86fd34e1e9bc2e39016 Mon Sep 17 00:00:00 2001 From: luohao Date: Wed, 8 Mar 2017 23:05:12 +0800 Subject: [PATCH 07/11] =?UTF-8?q?[add]=201.=20Java/Java=E7=9A=84=E2=80=9D?= =?UTF-8?q?=E4=B8=80=E6=AC=A1=E7=BC=96=E5=86=99=EF=BC=8C=E5=A4=84=E5=A4=84?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E2=80=9D=E6=98=AF=E5=A6=82=E4=BD=95=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E7=9A=84=3F.md=202.=20Java/=E9=9D=99=E6=80=81?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E6=9C=89=E4=BB=80=E4=B9=88=E7=89=B9=E7=82=B9?= =?UTF-8?q?=3F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\246\202\344\275\225\345\256\236\347\216\260\347\232\204?.md" | 0 ...\234\211\344\273\200\344\271\210\347\211\271\347\202\271?.md" | 1 + 2 files changed, 1 insertion(+) create mode 100644 "Java/Java\347\232\204\342\200\235\344\270\200\346\254\241\347\274\226\345\206\231\357\274\214\345\244\204\345\244\204\350\277\220\350\241\214\342\200\235\346\230\257\345\246\202\344\275\225\345\256\236\347\216\260\347\232\204?.md" create mode 100644 "Java/\351\235\231\346\200\201\347\261\273\345\236\213\346\234\211\344\273\200\344\271\210\347\211\271\347\202\271?.md" diff --git "a/Java/Java\347\232\204\342\200\235\344\270\200\346\254\241\347\274\226\345\206\231\357\274\214\345\244\204\345\244\204\350\277\220\350\241\214\342\200\235\346\230\257\345\246\202\344\275\225\345\256\236\347\216\260\347\232\204?.md" "b/Java/Java\347\232\204\342\200\235\344\270\200\346\254\241\347\274\226\345\206\231\357\274\214\345\244\204\345\244\204\350\277\220\350\241\214\342\200\235\346\230\257\345\246\202\344\275\225\345\256\236\347\216\260\347\232\204?.md" new file mode 100644 index 0000000..e69de29 diff --git "a/Java/\351\235\231\346\200\201\347\261\273\345\236\213\346\234\211\344\273\200\344\271\210\347\211\271\347\202\271?.md" "b/Java/\351\235\231\346\200\201\347\261\273\345\236\213\346\234\211\344\273\200\344\271\210\347\211\271\347\202\271?.md" new file mode 100644 index 0000000..1f6f878 --- /dev/null +++ "b/Java/\351\235\231\346\200\201\347\261\273\345\236\213\346\234\211\344\273\200\344\271\210\347\211\271\347\202\271?.md" @@ -0,0 +1 @@ +静态变量是和类绑定到一起的,而不是类的实例对象。每一个实例对象都共享同样一份静态变量。也就是说,一个类的静态变量只有一份,不管它有多少个对象。类变量或者说静态变量是通过`static`这个关键字来声明的。类变量通常被用作常量。静态变量通常通过类名字来进行访问。当程序运行的时候这个变量就会创建直到程序结束后才会被销毁。类变量的作用域和实例变量是一样的。它的初始值和成员变量也是一样的,当变量没被初始化的时候根据它的数据类型,会有一个默认值。类似的,静态方法是属于类的方法,而不是类对象,它的调用并不作用于类对象,也不需要创建任何的类实例。静态方法本身就是`final`的,因为重写只会发生在类实例上,静态方法是和类绑定在一起的,不是对象。父类的静态方法会被子类的静态方法屏蔽,只要原来方法没有声明为`final`。非静态方法不能重写静态方法,也就是说,你不能在子类中把一个静态方法改成实例方法。 From 3dfa311759aa4c2182c446e89a6e0d956908cd93 Mon Sep 17 00:00:00 2001 From: luohao Date: Thu, 9 Mar 2017 21:02:45 +0800 Subject: [PATCH 08/11] [update] --- ...05\345\255\230\346\250\241\345\236\213.md" | 31 +++++++++++++++++++ ...30\346\250\241\345\236\213\345\220\227.md" | 2 ++ Java/README.md | 2 ++ ...3`\346\230\257\344\273\200\344\271\210.md" | 17 ++++++++++ 4 files changed, 52 insertions(+) create mode 100644 "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\270\200)\344\273\200\344\271\210\346\230\257\345\206\205\345\255\230\346\250\241\345\236\213.md" create mode 100644 "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\272\214\357\274\211\345\205\266\344\273\226\350\257\255\350\250\200\357\274\214\345\203\217C++\357\274\214\344\271\237\346\234\211\345\206\205\345\255\230\346\250\241\345\236\213\345\220\227.md" create mode 100644 "Java/`Java`\345\206\205\345\255\230\346\250\241\345\236\213`FAQ`\357\274\210`\344\270\211`\357\274\211`JSR133`\346\230\257\344\273\200\344\271\210.md" diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\270\200)\344\273\200\344\271\210\346\230\257\345\206\205\345\255\230\346\250\241\345\236\213.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\270\200)\344\273\200\344\271\210\346\230\257\345\206\205\345\255\230\346\250\241\345\236\213.md" new file mode 100644 index 0000000..5f83328 --- /dev/null +++ "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\270\200)\344\273\200\344\271\210\346\230\257\345\206\205\345\255\230\346\250\241\345\236\213.md" @@ -0,0 +1,31 @@ +# `Java`内存模型`FAQ`(`一`)什么是内存模型 +在多核系统中,处理器一般有一层或者多层的缓存,这些的缓存通过加速数据访问(因为数据距离处理器更近)和降低共享内存在总线上的通讯(因为本地缓存能够满足许多内存操作)来提高`CPU`性能。缓存能够大大提升性能,但是它们也带来了许多挑战。例如,当两个`CPU`同时检查相同的内存地址时会发生什么?在什么样的条件下它们会看到相同的值? + +在处理器层面上,内存模型定义了一个充要条件,“让当前的处理器可以看到其他处理器写入到内存的数据”以及“其他处理器可以看到当前处理器写入到内存的数据”。有些处理器有很强的内存模型(`strong memory model`),能够让所有的处理器在任何时候任何指定的内存地址上都可以看到完全相同的值。而另外一些处理器则有较弱的内存模型(`weaker memory model`),在这种处理器中,必须使用内存屏障(一种特殊的指令)来刷新本地处理器缓存并使本地处理器缓存无效,目的是为了让当前处理器能够看到其他处理器的写操作或者让其他处理器能看到当前处理器的写操作。这些内存屏障通常在`lock`和`unlock`操作的时候完成。内存屏障在高级语言中对程序员是不可见的。 + +在强内存模型下,有时候编写程序可能会更容易,因为减少了对内存屏障的依赖。但是即使在一些最强的内存模型下,内存屏障仍然是必须的。设置内存屏障往往与我们的直觉并不一致。近来处理器设计的趋势更倾向于弱的内存模型,因为弱内存模型削弱了缓存一致性,所以在多处理器平台和更大容量的内存下可以实现更好的可伸缩性 + +“一个线程的写操作对其他线程可见”这个问题是因为编译器对代码进行重排序导致的。例如,只要代码移动不会改变程序的语义,当编译器认为程序中移动一个写操作到后面会更有效的时候,编译器就会对代码进行移动。如果编译器推迟执行一个操作,其他线程可能在这个操作执行完之前都不会看到该操作的结果,这反映了缓存的影响。 + +此外,写入内存的操作能够被移动到程序里更前的时候。在这种情况下,其他的线程在程序中可能看到一个比它实际发生更早的写操作。所有的这些灵活性的设计是为了通过给编译器,运行时或硬件灵活性使其能在最佳顺序的情况下来执行操作。在内存模型的限定之内,我们能够获取到更高的性能。 + +看下面代码展示的一个简单例子: + +``` +ClassReordering { + int x = 0, y = 0; + public void writer() { + x = 1; + y = 2; + } + public void reader() { + int r1 = y; + int r2 = x; + } +} +``` +让我们看在两个并发线程中执行这段代码,读取Y变量将会得到2这个值。因为这个写入比写到X变量更晚一些,程序员可能认为读取X变量将肯定会得到`1`。但是,写入操作可能被重排序过。如果重排序发生了,那么,就能发生对Y变量的写入操作,读取两个变量的操作紧随其后,而且写入到X这个操作能发生。程序的结果可能是`r1`变量的值是`2`,但是`r2`变量的值为`0`。 + +`Java`内存模型描述了在多线程代码中哪些行为是合法的,以及线程如何通过内存进行交互。它描述了“程序中的变量“ 和 ”从内存或者寄存器获取或存储它们的底层细节”之间的关系。`Java`内存模型通过使用各种各样的硬件和编译器的优化来正确实现以上事情。 + +`Java`包含了几个语言级别的关键字,包括:`volatile`, `final`以及`synchronized`,目的是为了帮助程序员向编译器描述一个程序的并发需求。`Java`内存模型定义了`volatile`和`synchronized`的行为,更重要的是保证了同步的`java`程序在所有的处理器架构下面都能正确的运行。 diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\272\214\357\274\211\345\205\266\344\273\226\350\257\255\350\250\200\357\274\214\345\203\217C++\357\274\214\344\271\237\346\234\211\345\206\205\345\255\230\346\250\241\345\236\213\345\220\227.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\272\214\357\274\211\345\205\266\344\273\226\350\257\255\350\250\200\357\274\214\345\203\217C++\357\274\214\344\271\237\346\234\211\345\206\205\345\255\230\346\250\241\345\236\213\345\220\227.md" new file mode 100644 index 0000000..4cfc581 --- /dev/null +++ "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\272\214\357\274\211\345\205\266\344\273\226\350\257\255\350\250\200\357\274\214\345\203\217C++\357\274\214\344\271\237\346\234\211\345\206\205\345\255\230\346\250\241\345\236\213\345\220\227.md" @@ -0,0 +1,2 @@ +# `Java`内存模型`FAQ`(`二`) 其他语言,像`C++`,也有内存模型吗? +大部分其他的语言,像C和C++,都没有被设计成直接支持多线程。这些语言对于发生在编译器和处理器平台架构的重排序行为的保护机制会严重的依赖于程序中所使用的线程库(例如pthreads),编译器,以及代码所运行的平台所提供的保障。 diff --git a/Java/README.md b/Java/README.md index 07fe480..ba60cb8 100644 --- a/Java/README.md +++ b/Java/README.md @@ -7,3 +7,5 @@ * `equals()`与`hashCode()`方法浅析 * `Java`的”一次编写,处处运行”是如何实现的 * 静态类型有什么特点? +* `Java`内存模型`FAQ`(`一`)什么是内存模型 +* `Java`内存模型`FAQ`(`二`) 其他语言,像`C++`,也有内存模型吗? diff --git "a/Java/`Java`\345\206\205\345\255\230\346\250\241\345\236\213`FAQ`\357\274\210`\344\270\211`\357\274\211`JSR133`\346\230\257\344\273\200\344\271\210.md" "b/Java/`Java`\345\206\205\345\255\230\346\250\241\345\236\213`FAQ`\357\274\210`\344\270\211`\357\274\211`JSR133`\346\230\257\344\273\200\344\271\210.md" new file mode 100644 index 0000000..5bf0361 --- /dev/null +++ "b/Java/`Java`\345\206\205\345\255\230\346\250\241\345\236\213`FAQ`\357\274\210`\344\270\211`\357\274\211`JSR133`\346\230\257\344\273\200\344\271\210.md" @@ -0,0 +1,17 @@ +# `Java`内存模型`FAQ`(`三`)`JSR133`是什么? +[原文](http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html )第三章 +从`1997`年以来,人们不断发现`Java`语言规范的`17`章定义的`Java`内存模型中的一些严重的缺陷。这些缺陷会导致一些使人迷惑的行为(例如`final`字段会被观察到值的改变)和破坏编译器常见的优化能力。 + +`Java`内存模型是一个雄心勃勃的计划,它是编程语言规范第一次尝试合并一个能够在各种处理器架构中为并发提供一致语义的内存模型。不过,定义一个既一致又直观的内存模型远比想象要更难。`JSR133`为`Java`语言定义了一个新的内存模型,它修复了早期内存模型中的缺陷。为了实现`JSR133`,`final`和`volatile`的语义需要重新定义。 + +[完整的语义见](http://www.cs.umd.edu/users/pugh/java/memoryModel),但是正式的语义不是小心翼翼的,它是令人惊讶和清醒的,目的是让人意识到一些看似简单的概念(如同步)其实有多复杂。幸运的是,你不需要懂得这些正式语义的细节——`JSR133`的目的是创建一组正式语义,这些正式语义提供了`volatile`、`synchronzied`和`final如`何工作的直观框架。 + +`JSR 133`的目标包含了: + +保留已经存在的安全保证(像类型安全)以及强化其他的安全保证。例如,变量值不能凭空创建:线程观察到的每个变量的值必须是被其他线程合理的设置的。 +正确同步的程序的语义应该尽量简单和直观。 +应该定义未完成或者未正确同步的程序的语义,主要是为了把潜在的安全危害降到最低。 +程序员应该能够自信的推断多线程程序如何同内存进行交互的。 +能够在现在许多流行的硬件架构中设计正确以及高性能的`JVM`实现。 +应该能提供 安全地初始化的保证。如果一个对象正确的构建了(意思是它的引用没有在构建的时候逸出,那么所有能够看到这个对象的引用的线程,在不进行同步的情况下,也将能看到在构造方法中中设置的`final`字段的值。 +应该尽量不影响现有的代码。 From 03d9207b14d773c2bd902cc2e5532b758184ef16 Mon Sep 17 00:00:00 2001 From: luohao Date: Fri, 10 Mar 2017 21:15:18 +0800 Subject: [PATCH 09/11] [update] --- ...03\344\273\254\347\232\204\345\200\274.md" | 1 + ...33\346\230\257\344\273\200\344\271\210.md" | 0 ...00\344\271\210\347\224\250\347\232\204.md" | 29 +++++++++++++ ...05\345\255\230\346\250\241\345\236\213.md" | 0 ...30\346\250\241\345\236\213\345\220\227.md" | 0 ...33\344\273\200\344\271\210\345\221\242.md" | 22 ++++++++++ ...25\345\267\245\344\275\234\347\232\204.md" | 42 +++++++++++++++++++ ...00\346\237\245\351\227\256\351\242\230.md" | 1 + ...00\344\271\210\351\227\256\351\242\230.md" | 9 ++++ ...11\346\230\257\344\273\200\344\271\210.md" | 7 ++++ ...63\347\235\200\344\273\200\344\271\210.md" | 8 ++++ Java/README.md | 9 ++++ ...00\344\271\210\347\211\271\347\202\271.md" | 0 13 files changed, 128 insertions(+) create mode 100644 "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213Final\345\255\227\346\256\265\345\246\202\344\275\225\346\224\271\345\217\230\345\256\203\344\273\254\347\232\204\345\200\274.md" rename "Java/`Java`\345\206\205\345\255\230\346\250\241\345\236\213`FAQ`\357\274\210`\344\270\211`\357\274\211`JSR133`\346\230\257\344\273\200\344\271\210.md" => "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213JSR133\346\230\257\344\273\200\344\271\210.md" (100%) create mode 100644 "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213volatile\346\230\257\345\271\262\344\273\200\344\271\210\347\224\250\347\232\204.md" rename "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\270\200)\344\273\200\344\271\210\346\230\257\345\206\205\345\255\230\346\250\241\345\236\213.md" => "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\344\273\200\344\271\210\346\230\257\345\206\205\345\255\230\346\250\241\345\236\213.md" (100%) rename "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\272\214\357\274\211\345\205\266\344\273\226\350\257\255\350\250\200\357\274\214\345\203\217C++\357\274\214\344\271\237\346\234\211\345\206\205\345\255\230\346\250\241\345\236\213\345\220\227.md" => "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\205\266\344\273\226\350\257\255\350\250\200\357\274\214\345\203\217C++\357\274\214\344\271\237\346\234\211\345\206\205\345\255\230\346\250\241\345\236\213\345\220\227.md" (100%) create mode 100644 "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\220\214\346\255\245\344\274\232\345\271\262\344\272\233\344\273\200\344\271\210\345\221\242.md" create mode 100644 "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\234\250\346\226\260\347\232\204Java\345\206\205\345\255\230\346\250\241\345\236\213\344\270\255\357\274\214final\345\255\227\346\256\265\346\230\257\345\246\202\344\275\225\345\267\245\344\275\234\347\232\204.md" create mode 100644 "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\226\260\347\232\204\345\206\205\345\255\230\346\250\241\345\236\213\346\230\257\345\220\246\344\277\256\345\244\215\344\272\206\345\217\214\351\207\215\351\224\201\346\243\200\346\237\245\351\227\256\351\242\230.md" create mode 100644 "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\227\247\347\232\204\345\206\205\345\255\230\346\250\241\345\236\213\346\234\211\344\273\200\344\271\210\351\227\256\351\242\230.md" create mode 100644 "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\262\241\346\234\211\346\255\243\347\241\256\345\220\214\346\255\245\347\232\204\345\220\253\344\271\211\346\230\257\344\273\200\344\271\210.md" create mode 100644 "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\351\207\215\346\216\222\345\272\217\346\204\217\345\221\263\347\235\200\344\273\200\344\271\210.md" rename "Java/\351\235\231\346\200\201\347\261\273\345\236\213\346\234\211\344\273\200\344\271\210\347\211\271\347\202\271?.md" => "Java/\351\235\231\346\200\201\347\261\273\345\236\213\346\234\211\344\273\200\344\271\210\347\211\271\347\202\271.md" (100%) diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213Final\345\255\227\346\256\265\345\246\202\344\275\225\346\224\271\345\217\230\345\256\203\344\273\254\347\232\204\345\200\274.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213Final\345\255\227\346\256\265\345\246\202\344\275\225\346\224\271\345\217\230\345\256\203\344\273\254\347\232\204\345\200\274.md" new file mode 100644 index 0000000..fceef7c --- /dev/null +++ "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213Final\345\255\227\346\256\265\345\246\202\344\275\225\346\224\271\345\217\230\345\256\203\344\273\254\347\232\204\345\200\274.md" @@ -0,0 +1 @@ +# `Java`内存模型`FAQ`(`八`)`Final`字段如何改变它们的值 diff --git "a/Java/`Java`\345\206\205\345\255\230\346\250\241\345\236\213`FAQ`\357\274\210`\344\270\211`\357\274\211`JSR133`\346\230\257\344\273\200\344\271\210.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213JSR133\346\230\257\344\273\200\344\271\210.md" similarity index 100% rename from "Java/`Java`\345\206\205\345\255\230\346\250\241\345\236\213`FAQ`\357\274\210`\344\270\211`\357\274\211`JSR133`\346\230\257\344\273\200\344\271\210.md" rename to "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213JSR133\346\230\257\344\273\200\344\271\210.md" diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213volatile\346\230\257\345\271\262\344\273\200\344\271\210\347\224\250\347\232\204.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213volatile\346\230\257\345\271\262\344\273\200\344\271\210\347\224\250\347\232\204.md" new file mode 100644 index 0000000..695cc83 --- /dev/null +++ "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213volatile\346\230\257\345\271\262\344\273\200\344\271\210\347\224\250\347\232\204.md" @@ -0,0 +1,29 @@ +# `Java`内存模型`FAQ`(`十`)`volatile`是干什么用的 +`Volatile`字段是用于线程间通讯的特殊字段。每次读`volatile`字段都会看到其它线程写入该字段的最新值;实际上,程序员之所以要定义`volatile`字段是因为在某些情况下由于缓存和重排序所看到的陈旧的变量值是不可接受的。编译器和运行时禁止在寄存器里面分配它们。它们还必须保证,在它们写好之后,它们被从缓冲区刷新到主存中,因此,它们立即能够对其他线程可见。相同地,在读取一个`volatile`字段之前,缓冲区必须失效,因为值是存在于主存中而不是本地处理器缓冲区。在重排序访问`volatile`变量的时候还有其他的限制。 + +在旧的内存模型下,访问`volatile`变量不能被重排序,但是,它们可能和访问非`volatile`变量一起被重排序。这破坏了`volatile`字段从一个线程到另外一个线程作为一个信号条件的手段。 + +在新的内存模型下,`volatile`变量仍然不能彼此重排序。和旧模型不同的时候,`volatile`周围的普通字段的也不再能够随便的重排序了。写入一个`volatile`字段和释放监视器有相同的内存影响,而且读取`volatile`字段和获取监视器也有相同的内存影响。事实上,因为新的内存模型在重排序`volatile`字段访问上面和其他字段(`volatile`或者非`volatile`)访问上面有了更严格的约束。当线程A写入一个`volatile`字段`f`的时候,如果线程`B`读取`f`的话 ,那么对线程`A`可见的任何东西都变得对线程`B`可见了。 + +如下例子展示了`volatile`字段应该如何使用: +``` +class VolatileExample { + int x = 0; + volatile boolean v = false; + public void writer() { + x = 42; + v = true; + } + + public void reader() { + if (v == true) { + //uses x - guaranteed to see 42. + } + } +} +``` +假设一个线程叫做“`writer`”,另外一个线程叫做“`reader`”。对变量`v`的写操作会等到变量`x`写入到内存之后,然后读线程就可以看见`v`的值。因此,如果`reader`线程看到了`v`的值为`true`,那么,它也保证能够看到在之前发生的写入`42`这个操作。而这在旧的内存模型中却未必是这样的。如果`v`不是`volatile`变量,那么,编译器可以在`writer`线程中重排序写入操作,那么`reader`线程中的读取`x`变量的操作可能会看到`0`。 + +实际上,`volatile`的语义已经被加强了,已经快达到同步的级别了。为了可见性的原因,每次读取和写入一个`volatile`字段已经像一个半同步操作了 + +重点注意:对两个线程来说,为了正确的设置`happens-before`关系,访问相同的`volatile`变量是很重要的。以下的结论是不正确的:当线程`A`写`volatile`字段`f`的时候,线程`A`可见的所有东西,在线程`B`读取`volatile`的字段`g`之后,变得对线程`B`可见了。释放操作和获取操作必须匹配(也就是在同一个`volatile`字段上面完成)。 diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\270\200)\344\273\200\344\271\210\346\230\257\345\206\205\345\255\230\346\250\241\345\236\213.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\344\273\200\344\271\210\346\230\257\345\206\205\345\255\230\346\250\241\345\236\213.md" similarity index 100% rename from "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\270\200)\344\273\200\344\271\210\346\230\257\345\206\205\345\255\230\346\250\241\345\236\213.md" rename to "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\344\273\200\344\271\210\346\230\257\345\206\205\345\255\230\346\250\241\345\236\213.md" diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\272\214\357\274\211\345\205\266\344\273\226\350\257\255\350\250\200\357\274\214\345\203\217C++\357\274\214\344\271\237\346\234\211\345\206\205\345\255\230\346\250\241\345\236\213\345\220\227.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\205\266\344\273\226\350\257\255\350\250\200\357\274\214\345\203\217C++\357\274\214\344\271\237\346\234\211\345\206\205\345\255\230\346\250\241\345\236\213\345\220\227.md" similarity index 100% rename from "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\357\274\210\344\272\214\357\274\211\345\205\266\344\273\226\350\257\255\350\250\200\357\274\214\345\203\217C++\357\274\214\344\271\237\346\234\211\345\206\205\345\255\230\346\250\241\345\236\213\345\220\227.md" rename to "Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\205\266\344\273\226\350\257\255\350\250\200\357\274\214\345\203\217C++\357\274\214\344\271\237\346\234\211\345\206\205\345\255\230\346\250\241\345\236\213\345\220\227.md" diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\220\214\346\255\245\344\274\232\345\271\262\344\272\233\344\273\200\344\271\210\345\221\242.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\220\214\346\255\245\344\274\232\345\271\262\344\272\233\344\273\200\344\271\210\345\221\242.md" new file mode 100644 index 0000000..5cfca75 --- /dev/null +++ "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\220\214\346\255\245\344\274\232\345\271\262\344\272\233\344\273\200\344\271\210\345\221\242.md" @@ -0,0 +1,22 @@ +# `Java`内存模型`FAQ`(`七`)同步会干些什么呢 +同步有几个方面的作用。最广为人知的就是互斥 ——一次只有一个线程能够获得一个监视器,因此,在一个监视器上面同步意味着一旦一个线程进入到监视器保护的同步块中,其他的线程都不能进入到同一个监视器保护的块中间,除非第一个线程退出了同步块。 + +但是同步的含义比互斥更广。同步保证了一个线程在同步块之前或者在同步块中的一个内存写入操作以可预知的方式对其他有相同监视器的线程可见。当我们退出了同步块,我们就释放了这个监视器,这个监视器有刷新缓冲区到主内存的效果,因此该线程的写入操作能够为其他线程所见。在我们进入一个同步块之前,我们需要获取监视器,监视器有使本地处理器缓存失效的功能,因此变量会从主存重新加载,于是其它线程对共享变量的修改对当前线程来说就变得可见了。 + +依据缓存来讨论同步,可能听起来这些观点仅仅会影响到多处理器的系统。但是,重排序效果能够在单一处理器上面很容易见到。对编译器来说,在获取之前或者释放之后移动你的代码是不可能的。当我们谈到在缓冲区上面进行的获取和释放操作,我们使用了简述的方式来描述大量可能的影响。 + +新的内存模型语义在内存操作(读取字段,写入字段,锁,解锁)以及其他线程的操作(`start` 和 `join`)中创建了一个部分排序,在这些操作中,一些操作被称为`happen before`其他操作。当一个操作在另外一个操作之前发生,第一个操作保证能够排到前面并且对第二个操作可见。这些排序的规则如下: +线程中的每个操作`happens before`该线程中在程序顺序上后续的每个操作。 +解锁一个监视器的操作`happens before`随后对相同监视器进行锁的操作。 +对`volatile`字段的写操作`happens before`后续对相同`volatile`字段的读取操作。 +线程上调用`start()`方法`happens before`这个线程启动后的任何操作。 +一个线程中所有的操作都`happens before`从这个线程`join()`方法成功返回的任何其他线程。(注意思是其他线程等待一个线程的`jion()`方法完成,那么,这个线程中的所有操作`happens before`其他线程中的所有操作) +这意味着:任何内存操作,这个内存操作在退出一个同步块前对一个线程是可见的,对任何线程在它进入一个被相同的监视器保护的同步块后都是可见的,因为所有内存操作`happens before`释放监视器以及释放监视器`happens before`获取监视器。 + +其他如下模式的实现被一些人用来强迫实现一个内存屏障的,不会生效: +``` +synchronized (new Object()) {} +``` +这段代码其实不会执行任何操作,你的编译器会把它完全移除掉,因为编译器知道没有其他的线程会使用相同的监视器进行同步。要看到其他线程的结果,你必须为一个线程建立`happens before`关系。 + +重点注意:对两个线程来说,为了正确建立`happens before`关系而在相同监视器上面进行同步是非常重要的。以下观点是错误的:当线程`A`在对象`X`上面同步的时候,所有东西对线程`A`可见,线程`B`在对象`Y`上面进行同步的时候,所有东西对线程`B`也是可见的。释放监视器和获取监视器必须匹配(也就是说要在相同的监视器上面完成这两个操作),否则,代码就会存在“数据竞争”。 diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\234\250\346\226\260\347\232\204Java\345\206\205\345\255\230\346\250\241\345\236\213\344\270\255\357\274\214final\345\255\227\346\256\265\346\230\257\345\246\202\344\275\225\345\267\245\344\275\234\347\232\204.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\234\250\346\226\260\347\232\204Java\345\206\205\345\255\230\346\250\241\345\236\213\344\270\255\357\274\214final\345\255\227\346\256\265\346\230\257\345\246\202\344\275\225\345\267\245\344\275\234\347\232\204.md" new file mode 100644 index 0000000..8361e0e --- /dev/null +++ "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\345\234\250\346\226\260\347\232\204Java\345\206\205\345\255\230\346\250\241\345\236\213\344\270\255\357\274\214final\345\255\227\346\256\265\346\230\257\345\246\202\344\275\225\345\267\245\344\275\234\347\232\204.md" @@ -0,0 +1,42 @@ +# `Java`内存模型`FAQ`(`九`)在新的`Java`内存模型中,`final`字段是如何工作的 +一个对象的`final`字段值是在它的构造方法里面设置的。假设对象被正确的构造了,一旦对象被构造,在构造方法里面设置给`final`字段的的值在没有同步的情况下对所有其他的线程都会可见。另外,引用这些`final`字段的对象或数组都将会看到`final`字段的最新值。 + +对一个对象来说,被正确的构造是什么意思呢?简单来说,它意味着这个正在构造的对象的引用在构造期间没有被允许逸出。(参见安全构造技术)。换句话说,不要让其他线程在其他地方能够看见一个构造期间的对象引用。不要指派给一个静态字段,不要作为一个listener注册给其他对象等等。这些操作应该在构造方法之后完成,而不是构造方法中来完成。 +``` +class FinalFieldExample { + final int x; + int y; + static FinalFieldExample f; + public FinalFieldExample() { + x = 3; + y = 4; + } + + static void writer() { + f = new FinalFieldExample(); + } + + static void reader() { + if (f != null) { + int i = f.x; + int j = f.y; + } + } +} +``` +上面的类展示了`final`字段应该如何使用。一个正在执行`reader`方法的线程保证看到`f.x`的值为`3`,因为它是`final`字段。它不保证看到`f.y`的值为`4`,因为`f.y`不是`final`字段。如果`FinalFieldExample`的构造方法像这样: +``` +public FinalFieldExample() { // bad! + x = 3; + y = 4; + // bad construction - allowing this to escape + global.obj = this; +} +``` +那么,从`global.obj`中读取`this`的引用线程不会保证读取到的`x`的值为`3`。 + +能够看到字段的正确的构造值固然不错,但是,如果字段本身就是一个引用,那么,你还是希望你的代码能够看到引用所指向的这个对象(或者数组)的最新值。如果你的字段是`final`字段,那么这是能够保证的。因此,当一个`final`指针指向一个数组,你不需要担心线程能够看到引用的最新值却看不到引用所指向的数组的最新值。重复一下,这儿的“正确的”的意思是“对象构造方法结尾的最新的值”而不是“最新可用的值”。 + +现在,在讲了如上的这段之后,如果在一个线程构造了一个不可变对象之后(对象仅包含`final`字段),你希望保证这个对象被其他线程正确的查看,你仍然需要使用同步才行。例如,没有其他的方式可以保证不可变对象的引用将被第二个线程看到。使用`final`字段的程序应该仔细的调试,这需要深入而且仔细的理解并发在你的代码中是如何被管理的。 + +如果你使用`JNI`来改变你的`final`字段,这方面的行为是没有定义的。 diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\226\260\347\232\204\345\206\205\345\255\230\346\250\241\345\236\213\346\230\257\345\220\246\344\277\256\345\244\215\344\272\206\345\217\214\351\207\215\351\224\201\346\243\200\346\237\245\351\227\256\351\242\230.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\226\260\347\232\204\345\206\205\345\255\230\346\250\241\345\236\213\346\230\257\345\220\246\344\277\256\345\244\215\344\272\206\345\217\214\351\207\215\351\224\201\346\243\200\346\237\245\351\227\256\351\242\230.md" new file mode 100644 index 0000000..b4a92cf --- /dev/null +++ "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\226\260\347\232\204\345\206\205\345\255\230\346\250\241\345\236\213\346\230\257\345\220\246\344\277\256\345\244\215\344\272\206\345\217\214\351\207\215\351\224\201\346\243\200\346\237\245\351\227\256\351\242\230.md" @@ -0,0 +1 @@ +# `Java`内存模型`FAQ`(`十一`)新的内存模型是否修复了双重锁检查问题? diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\227\247\347\232\204\345\206\205\345\255\230\346\250\241\345\236\213\346\234\211\344\273\200\344\271\210\351\227\256\351\242\230.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\227\247\347\232\204\345\206\205\345\255\230\346\250\241\345\236\213\346\234\211\344\273\200\344\271\210\351\227\256\351\242\230.md" new file mode 100644 index 0000000..72bda1b --- /dev/null +++ "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\227\247\347\232\204\345\206\205\345\255\230\346\250\241\345\236\213\346\234\211\344\273\200\344\271\210\351\227\256\351\242\230.md" @@ -0,0 +1,9 @@ +# Java内存模型FAQ(五)旧的内存模型有什么问题? +旧的内存模型中有几个严重的问题。这些问题很难理解,因此被广泛的违背。例如,旧的存储模型在许多情况下,不允许`JVM`发生各种重排序行为。旧的内存模型中让人产生困惑的因素造就了JSR-133规范的诞生。 + + +例如,一个被广泛认可的概念就是,如果使用`final`字段,那么就没有必要在多个线程中使用同步来保证其他线程能够看到这个字段的值。尽管这是一个合理的假设和明显的行为,也是我们所期待的结果。实际上,在旧的内存模型中,我们想让程序正确运行起来却是不行的。在旧的内存模型中,`final`字段并没有同其他字段进行区别对待——这意味着同步是保证所有线程看到一个在构造方法中初始化的final字段的唯一方法。结果——如果没有正确同步的话,对一个线程来说,它可能看到一个字段的默认值,然后在稍后的时间里,又能够看到构造方法中设置的值。这意味着,一些不可变的对象,例如`String`,能够改变它们值——这实在很让人郁闷。 + +旧的内存模型允许`volatile`变量的写操作和非`volaitle`变量的读写操作一起进行重排序,这和大多数的开发人员对于`volatile`变量的直观感受是不一致的,因此会造成迷惑。 + +最后,我们将看到的是,程序员对于程序没有被正确同步的情况下将会发生什么的直观感受通常是错误的。`JSR-133`的目的之一就是要引起这方面的注意。 diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\262\241\346\234\211\346\255\243\347\241\256\345\220\214\346\255\245\347\232\204\345\220\253\344\271\211\346\230\257\344\273\200\344\271\210.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\262\241\346\234\211\346\255\243\347\241\256\345\220\214\346\255\245\347\232\204\345\220\253\344\271\211\346\230\257\344\273\200\344\271\210.md" new file mode 100644 index 0000000..9807134 --- /dev/null +++ "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\346\262\241\346\234\211\346\255\243\347\241\256\345\220\214\346\255\245\347\232\204\345\220\253\344\271\211\346\230\257\344\273\200\344\271\210.md" @@ -0,0 +1,7 @@ +# `Java`内存模型`FAQ`(`六`)没有正确同步的含义是什么? +没有正确同步的代码对于不同的人来说可能会有不同的理解。在`Java`内存模型这个语义环境下,我们谈到“没有正确同步”,我们的意思是: + +一个线程中有一个对变量的写操作, +另外一个线程对同一个变量有读操作, +而且写操作和读操作没有通过同步来保证顺序。 +当这些规则被违反的时候,我们就说在这个变量上有一个“数据竞争”(`data race`)。一个有数据竞争的程序就是一个没有正确同步的程序。 diff --git "a/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\351\207\215\346\216\222\345\272\217\346\204\217\345\221\263\347\235\200\344\273\200\344\271\210.md" "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\351\207\215\346\216\222\345\272\217\346\204\217\345\221\263\347\235\200\344\273\200\344\271\210.md" new file mode 100644 index 0000000..3ad5aea --- /dev/null +++ "b/Java/Java\345\206\205\345\255\230\346\250\241\345\236\213FAQ\344\271\213\351\207\215\346\216\222\345\272\217\346\204\217\345\221\263\347\235\200\344\273\200\344\271\210.md" @@ -0,0 +1,8 @@ +# Java内存模型FAQ(四)重排序意味着什么? +在很多情况下,访问一个程序变量(对象实例字段,类静态字段和数组元素)可能会使用不同的顺序执行,而不是程序语义所指定的顺序执行。编译器能够自由的以优化的名义去改变指令顺序。在特定的环境下,处理器可能会次序颠倒的执行指令。数据可能在寄存器,处理器缓冲区和主内存中以不同的次序移动,而不是按照程序指定的顺序。 + +例如,如果一个线程写入值到字段`a`,然后写入值到字段`b`,而且`b`的值不依赖于`a`的值,那么,处理器就能够自由的调整它们的执行顺序,而且缓冲区能够在`a`之前刷新b的值到主内存。有许多潜在的重排序的来源,例如编译器,`JIT`以及缓冲区。 + +编译器,运行时和硬件被期望一起协力创建好像是顺序执行的语义的假象,这意味着在单线程的程序中,程序应该是不能够观察到重排序的影响的。但是,重排序在没有正确同步了的多线程程序中开始起作用,在这些多线程程序中,一个线程能够观察到其他线程的影响,也可能检测到其他线程将会以一种不同于程序语义所规定的执行顺序来访问变量。 + +大部分情况下,一个线程不会关注其他线程正在做什么,但是当它需要关注的时候,这时候就需要同步了。 diff --git a/Java/README.md b/Java/README.md index ba60cb8..e656a7b 100644 --- a/Java/README.md +++ b/Java/README.md @@ -9,3 +9,12 @@ * 静态类型有什么特点? * `Java`内存模型`FAQ`(`一`)什么是内存模型 * `Java`内存模型`FAQ`(`二`) 其他语言,像`C++`,也有内存模型吗? +* `Java`内存模型`FAQ`(`三`)`JSR133`是什么? +* `Java`内存模型`FAQ`(`四`)重排序意味着什么? +* `Java`内存模型`FAQ`(`五`)旧的内存模型有什么问题? +* `Java`内存模型`FAQ`(`六`)没有正确同步的含义是什么? +* `Java`内存模型`FAQ`(`七`)同步会干些什么呢 +* `Java`内存模型`FAQ`(`八`)`Final`字段如何改变它们的值 +* `Java`内存模型`FAQ`(`九`)在新的`Java`内存模型中,`final`字段是如何工作的 +* `Java`内存模型`FAQ`(`十`)`volatile`是干什么用的 +* `Java`内存模型`FAQ`(`十一`)新的内存模型是否修复了双重锁检查问题? diff --git "a/Java/\351\235\231\346\200\201\347\261\273\345\236\213\346\234\211\344\273\200\344\271\210\347\211\271\347\202\271?.md" "b/Java/\351\235\231\346\200\201\347\261\273\345\236\213\346\234\211\344\273\200\344\271\210\347\211\271\347\202\271.md" similarity index 100% rename from "Java/\351\235\231\346\200\201\347\261\273\345\236\213\346\234\211\344\273\200\344\271\210\347\211\271\347\202\271?.md" rename to "Java/\351\235\231\346\200\201\347\261\273\345\236\213\346\234\211\344\273\200\344\271\210\347\211\271\347\202\271.md" From 616bb8dfa17cd653021e3895c31df0f9332e63fc Mon Sep 17 00:00:00 2001 From: luohao Date: Wed, 15 Mar 2017 09:19:19 +0800 Subject: [PATCH 10/11] [update] --- ...5\246\202\344\275\225\345\256\236\347\216\260\347\232\204.md" | 1 + ...\246\202\344\275\225\345\256\236\347\216\260\347\232\204?.md" | 0 2 files changed, 1 insertion(+) create mode 100644 "Java/Java\347\232\204\342\200\235\344\270\200\346\254\241\347\274\226\345\206\231\357\274\214\345\244\204\345\244\204\350\277\220\350\241\214\342\200\235\346\230\257\345\246\202\344\275\225\345\256\236\347\216\260\347\232\204.md" delete mode 100644 "Java/Java\347\232\204\342\200\235\344\270\200\346\254\241\347\274\226\345\206\231\357\274\214\345\244\204\345\244\204\350\277\220\350\241\214\342\200\235\346\230\257\345\246\202\344\275\225\345\256\236\347\216\260\347\232\204?.md" diff --git "a/Java/Java\347\232\204\342\200\235\344\270\200\346\254\241\347\274\226\345\206\231\357\274\214\345\244\204\345\244\204\350\277\220\350\241\214\342\200\235\346\230\257\345\246\202\344\275\225\345\256\236\347\216\260\347\232\204.md" "b/Java/Java\347\232\204\342\200\235\344\270\200\346\254\241\347\274\226\345\206\231\357\274\214\345\244\204\345\244\204\350\277\220\350\241\214\342\200\235\346\230\257\345\246\202\344\275\225\345\256\236\347\216\260\347\232\204.md" new file mode 100644 index 0000000..f4a9f9a --- /dev/null +++ "b/Java/Java\347\232\204\342\200\235\344\270\200\346\254\241\347\274\226\345\206\231\357\274\214\345\244\204\345\244\204\350\277\220\350\241\214\342\200\235\346\230\257\345\246\202\344\275\225\345\256\236\347\216\260\347\232\204.md" @@ -0,0 +1 @@ +# `Java`的”一次编写,处处运行”是如何实现的? diff --git "a/Java/Java\347\232\204\342\200\235\344\270\200\346\254\241\347\274\226\345\206\231\357\274\214\345\244\204\345\244\204\350\277\220\350\241\214\342\200\235\346\230\257\345\246\202\344\275\225\345\256\236\347\216\260\347\232\204?.md" "b/Java/Java\347\232\204\342\200\235\344\270\200\346\254\241\347\274\226\345\206\231\357\274\214\345\244\204\345\244\204\350\277\220\350\241\214\342\200\235\346\230\257\345\246\202\344\275\225\345\256\236\347\216\260\347\232\204?.md" deleted file mode 100644 index e69de29..0000000 From 09504cd7cbcb33013d693a0cce144df14f88cde0 Mon Sep 17 00:00:00 2001 From: luohao Date: Wed, 15 Mar 2017 22:44:42 +0800 Subject: [PATCH 11/11] =?UTF-8?q?[update]=20Java/=E6=B7=B1=E5=85=A5?= =?UTF-8?q?=E7=90=86=E8=A7=A3Java=E5=86=85=E5=AD=98=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=EF=BC=88=E4=B8=80=EF=BC=89=E2=80=94=E2=80=94=E5=9F=BA=E7=A1=80?= =?UTF-8?q?.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Java/Picture/310.png | Bin 0 -> 9420 bytes Java/Picture/3101.png | Bin 0 -> 2999 bytes Java/Picture/44.png | Bin 0 -> 13028 bytes Java/Picture/55.png | Bin 0 -> 15695 bytes Java/Picture/JVMAbstractNeiCunModel.png | Bin 0 -> 13390 bytes Java/README.md | 1 + ...24\342\200\224\345\237\272\347\241\200.md" | 76 ++++++++++++++++++ 7 files changed, 77 insertions(+) create mode 100644 Java/Picture/310.png create mode 100644 Java/Picture/3101.png create mode 100644 Java/Picture/44.png create mode 100644 Java/Picture/55.png create mode 100644 Java/Picture/JVMAbstractNeiCunModel.png create mode 100644 "Java/\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213\357\274\210\344\270\200\357\274\211\342\200\224\342\200\224\345\237\272\347\241\200.md" diff --git a/Java/Picture/310.png b/Java/Picture/310.png new file mode 100644 index 0000000000000000000000000000000000000000..0d20bb891fb32e4b23615cde8be3a087a230c776 GIT binary patch literal 9420 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 aT~N`rO*|7+Dp#dM2Y_`=K-D^q5&r=pYqYcg literal 0 HcmV?d00001 diff --git a/Java/Picture/44.png b/Java/Picture/44.png new file mode 100644 index 0000000000000000000000000000000000000000..8bf4a37bb05db065d5f154cea27d4e00105ea48c GIT binary patch literal 13028 zcmbum1ys~gxGy@C(jp+8I!cI0cMBqtBMv3qAqdiqh;%4O4JpXbEz;ec!$_Baba&m& zIrp8n-g;}Dd+)liX0c}2v;VQb{e8dq{vm2A@=^I~p8YFrM+k(t?e>Kc`;?d#0%3wE$V$I;OWsORwVYZ{ z+A)}8}>-4!kB{)+E3zIbj5`a&_4}r+w1k*quKQLv9 zAbx5X8FwI3IS?2Ygz2qc4hDpTU1|&h!F}-m8{R?-OG-JvCPI7q!*{lv!g88xMO zB)q5)7x}6!>EitE>AipiYOkt>^PZtA?Elqt55HzmgvbWg(QoJkWn(}%(>0bBQ_(n0 zQAgd>fx{O}g^t#N$(#APf=%IA6_XO54#xsbr~=Rah}cd8 z!;r}iWo?x0=^(WjvA8bikd_{bIJ;py`P&fhlt^Q%?e1vr zTZ*94j7@STs@hL*qM3|;)OXw3K2Y-u^FX|V;_9+k-pesSFXm%^p7=KXS4w(z<6eEO(8kyW#ZlkkilC9xgv7xaF4YwL_H`7X=7(^R(c z^$)nknrB-U97Q|xI2dI7<usQl3-wOxv(e`kY58)Ahb1a`D?MD5<0j_>!NA zmsiJVhNbtTL%c)ZOg%B-2m z$CEA|l-FAnNAc&#~8`xUc>`jhBrYa3}F&(9k= zJ0I2VG+bPr%vm9ht4#equ*Ub+6oq97HRnSWd{10`U3XFiza8e@|6R-ynvs`R#vz{x zQ;1Hk+uqtzF8o7FOIxjLXJqt4BmWsE=Lnx32gQ9EZ0VdlkqTpo%aC&l6RxVAx0lx@ z6k5Ddb2i$f1!W}t{mDNoD{E#(&!6d4^cbJ*qGsx+1e=Q>;WA^A;$kP|qx=1UL!wd=m z)vfk0O2XEJbwiD+ZvDAN-$4huWA>*Cq|zjJ@7@gy3qv5S5aX77Br-2V5|}KmrO`*( zs%gkKYym@id)%#DiApPA0&+QJ?HNDj0NeEWzkg*%`Bq)@>)bvmD!+xp;YX*Zr|avl zNwDE?$7;Gxhoqz=!q)J*WV4CUQFV^T7<3;U9ESIh{hby986mPQUTw1!_qgzWWCzNH ztEi~#pVhUlXp+mp$k{^Qz)_oeDu!R7-9smo{+OK(dd!#y!_(8#|7wahYVz_zWHU7K z*+Px8+cBphVingyl=7p`!`h8=-_#vs?aq0t$vFmf|(mp4>R!v0L}ZEcA>g0ZDH zx3*y9@Z7hi+Ou_bsmVzi8C1`A=H>eRGb#6(kmHOTnQ0uo9md?NU!-v#$0%rVEHl$}E`$cJ)ezr*qluwfD5=%< z4ceWR^_T-Io?Px~;hwKw`&KHG!pQhI1%-MUM_2}~qm%Aqs*ER_o48kzFCWfydOuKq zfvaa=U}Cj^=bwY#7_!|17uc6oHSkG0NSz5c16e05BqHLLIW5e(DZ40Nzk1#Sz7di^ z71fzCC5@}6tJ_4C!&2vcK@lHS*Vq{K^dSb}Lr4bF>uclO$|(x%f5dv5)vHruu2ym# z=rnWRmRv#w1O;7PT~nqoI%MLOmzT|SG5SF~wy?u0_ZoBXikB^df@-J!foy*MzR}$p z_XoHnh3Jw5kIPeT(}xHi^CwR^kdaYQSNo>{DX%C)YW05jl%}N5yTa6G>C!DYWH!rf z$3}6sKF^8q2Miq@@fUSW=$Zt#lN*x3$Vb=sDAd=SL=u&ZxtG5e)6;L)8BqlqQAIfZ z5<%ZD#kifw5k{t8yf428vUmt1^Vkf|Rx18!)Ul#B6MeY~}O#=gIR@ zwO`33ENkwY(i2Kb%4Y2(n(XXsj$UJKIoR6@op$3Mq5yRM;&`Ov2Xr{ldk)s+%{3yP#J2 z;yAqJC)O_R{d{*W6tVy0zNC!&p33EjnBOU?x+~J}YYAE6yX9fnrJa!DPb%d(u((Ej zohiM`m!$8BMg5r))^?MVM)(SK3XRkHxb4)kf>f0Hb28lQbr2%&)0eT`Unk=Z9>EQZp~nM_~DNH^i+F1Ir(^l(eY@ zb9k_qTL;A!sc1Z@#hKn`2czwT$d z^0G4jr$x_0jen?ttxP+YAvkwR(Mf%~v_@nV%$aG&Gkkyjv(5b#S@-ZchrSeTe38LG zn-V*Iw&g(H;a-!H76N%;g7VQp?!8b6!xM0ArCQ;u?yD}i{!M21|H4>9Lu4@(^Ub$| zx2?@1OLaE1!PS@>gcG(>k*Yeks%Ns|qYs^;q0GbSo?L{VZ88d~&G;$Q>xB~f?whwf zu{H@A{(7gMNHqd!rQ3>AsK)p*N1CF#_v0zzR^_1 z!D(UZ;BY^TKAk`g#vY3wCtO)mbaOR#bH%6bNqp}=hccS4mB@_p6%Bjqp;c8?OA{~) zcEzG>?9UDloq9aI|DR!Lp4Q}Y3;QL;rBp==!s(xjHo)6;t`6hUwGZ*UOQC@+EY=by zW4QkF?$_(UEa1!ZvaQg^f zK5#$npO+(-(-j`ILg?%3cNpVSg_VRL20_4+C`4ENHXi1)H8R2oV{7_*usT?!)V}19 z;If1V=DG2-hAL>VgAEFDZBgMAB!Fb_Ac{e}N1y$H!;AvBF%! zmc9gu*-{{BV52^R6;wO@V$ok%Oab=oM`qgk+S<7&Ypnu|B~mWf#Z=?fJ9XUY*_E2N z>}xeeRx}FHe9G?(`lC&G5<}iO`!nej#$~V$baGlDicr?(!t@A)!|&g}Z>x4M4J#rD z`@?=|Vu}omJkBgzOz#~W9t~v_b2IdKsd8Bm76t;KM0OmEXAt-J{yHl;31J3RFs8br zn8y9>6*)eRp!pQtewG1HEE~g2MPdm=&I=vEGbxdhwjZc~cEXIhlcuaSd z>mxn1*=@aEb#DL(=KV6j3MGFvP|n^qHUvB_LPp-+^k{+2XsEEZ2zzf?UfyT@QgYSN zU(&@3TIu^1S{_oVQY39BbG|oeH)m;c-X}AXSEG_w=NrXtSJryyo5Sq?c;kCMns&X% zc(Zr0)7WWA$4nm9?xc6KUAsd!S?#)`&q1LMe_$@B99XpBdm!k0u#N)d1*-5dBT7_M zwDIP;c49Kovt7sFW^3;H8AaGkt)LNWvQa{BuOb5JX)ri2;B#|z5)%{Sdm7}MP_^r0 zr1lzVIBZ=(6Y-KgHV-T(VchF1^YTQM>{6`_#d`g@si{`u_4D%@kes;rKmXEsri(=M zBU>$WiqRWK9ujGtT6y1oP1yz-A>HLQ@vKkE2^@8K;(O&Xhwt8F5W@Qv+iT_sFE83C z8bDi6-9ekXZf7wk;|K@{*e}1N#BN?7VQ=N)Q%-8e<_Nj>vaF)Q+1VMMkCNf_WBAEN z|A;%Y9Ayn3{U!SlR;ba5e+70SYiI^5Ve8)m_sZ8+(qPl^ul2@1AHqt3D36x(jc;o? z+66EL*Vl{7!6baI>B8El6=yg@7eV0`NP4Wmqon@j#bU1Z57toR+Uu-0obiGJ0-IyJ zaCrZphtebfDXP;d=^7Yx#zxt@yHod?cb5mUhE|QZ;QLFFU~_u&c`_`2tk&hMz27)D zImvSnY&b2_$`a6{UM>@D3Lw*ym=!+G$ffgf0X;OBxsUsFZE%hmcd>HLr`7oNDBqt2 zH%yRED_m=6M}+{gxGxjMD9IW7x=L3db(JmD<8=2&^|M6B&pwX=QV|dQnee~Jh@{N^ z`J)D}=#B3-W~_7rNV{#ZpxwB1h_G9gNDmE`*FJG_a`L0XBkKx8 z2CJf?BJq|b!kn`l&DY-z)lVb)2-~pt_KqOwG38nLo;*4_y0o;!=zIAMxn|0<_TwUg z8(-iZ20!4yCRJ^;S*tI4OML{eG0;7ZdT8|c_;mg&j$VBO0}Gx+fYZAqUZZZ6v1ZeavyU|m{%umbA zlM5>=9oNuKm)ewmbAm7aQ(61>%15pac>#@>&MuLO{>jn1GUoWS=kD2sZKQ$s)fU$A z?$@hxd1uiXjAb)np&6+X-X6}* z{9aw};+EaSuJ@M}!`Ut`?*$`HKrwvU(d?i*NR_;+b{ zdRLnc9#Q;eM%pdNC2jPoxUR0Q?dXH*lbEVNHCvfzXm8ny+dmWvJ{Q{vqU8y0hEAbM zxuFk4w%-$gl!^&@IoQ*uPsbniBw-zf%LRM?j))}oXkBUbIhLM(w^|mu_^m6_@J#8C z`$@sOl?I2KYj52bPaPc{wKl`Ugkfu-Bq5O6okO5{f}i5zVk-pk1RdWyw}}%RJ3u3v z&DOWq(F1Nxnl;8M^;o#l8LCQKQAGcOOux!*yoEAf2T6XZqDML-)y61>X#emZaz$D-t>C3DUAzgf86Dig^^<$efV&X zIUvBbF;y_UI5lDa33uhWicsB_Bijekom4n+%G?MeE2GcK{S&eX5}8+jCZxXLhmpv% zBnciK*jaox)7I@qfOO0t;q|Xutdn@yl8+{$!RsvAC?V(`M5RIM_7F@Jo^sqlVv8kXbx`aVE zWonOk?a9OBbbB?{k3^(N2A_5~Zoq0Tn)-MoB|j8#IYj2=)z;Q(DPdGWUNO$fu-AdielDqcZHP7LRkT8mpg?zi2Z`x%>sJwrA9Tevcmv`WeQ z^0d^Z3uhPW`a#8Z8;>isdxJ3X$XVBdawiWDHv;KgcsGG698a$`0BKeAHpX#cs@l4V+`s#|clt39%9!(a@r4BDrihu-9 zk`(L*yw5>t#fjeY{GRfy+PhRq;vJZz^(1yPBPiAm7k zpxITs%K!Cf-Z51?c?6=OK|*KluAyyhcmzg3=Pfu^+c^-VPc1)5c!gvDpcu0-h%#K%V zq>?^_2^T0}RrmsR6OnF=dem{xW-752#yqCt26#8behe(_)X|@CdcPa+iD0;@GX~`P zt({)Q6jtEEFNH@69}9%lULYJoGwh$$<8y+ERt|rCYuI{4705;rHV|f->3_ylWBlpr zQQUkFA8vHck7jy>CA*;?jzd(_SoDXdL7!J`!u>OViV_&qTEJghNwh;}N(Jce`;K@D ztxBVvBjZg;T|Km>hDOO>j7o#%f<+tevKQ;e_8#I`qBZ8`iWdJ$?UsqYdUR!%aEN-1 z_ziz3d$Wqtv5AkjV7;sI9Ef2HtwH7|sKo~ZT`~X-6 ziTyMBt@d5G(--m0qlZ{LDv*p7P1ew|9V4P0={DoiMCWm+LTKmGifJV0-SLt(^j9J| zb$Be&N|Unm9{Xpwf8pJrL#Yb{&Dbja$QjW?ChKdt=$}hVCZZNPShG1S`^wROo0~C; zocEjkGjena$33T!U$tRyl(-;K6K>nsr6PN58Lxqp8hOWSfuxlFdM2`vfNGdKdT+L2 z_7%3Y7C;x;LQV8d>IcuE3Il_KQFJ!t>^dxyBhHaU8=y?OWPO)-2}fC1OltNAUHtYQ zcBVJyxr<4{ef!sfzHw0L39pSJ0c+^w^z^2}Z6?6Bup-_}a3;GGcz%;h@30e|D zAWQpL{!C9Ne@p&Gm2FT5$|O{QqymDGssj-M8c_w&NOQCFKVFxAH9qd{AvWTpD=SZm zwsic~AQ=>pvI&l&T{Vfcv@eBP0P=*kgBk{$oT`04tWgZvXH=K_z0U!zP#UGc)UWsW z!d*0H$!DL4iNp%lfizW3(D#;+%YCW6i+G)7PjvtN`}YA2M7WGh*3D9JX1cF`vc3+M zE7avQ(APKK8+!}yUp*)hVYm0onUVXmx4KQ5`xYOqB@L8-(vxO~X&`}8r~^vbMVRmv zBg1?_;7jQ}W?W2kowh$y%X;ow&GmdUmM#Xr9{Pfl9>@MEyA!R z!|Rn7YXxgHK8}u`%>se!%qZ#OWOp~=mf$ZdFWQ(F$f8qQ<|InzJ5yJfxVE`fMx9t4 zUz+n!>(X~DD9U3w%A+y@zvM~UfS7oj^#j?T-Ss@J$S4m&*&c34K2445aBg{Q-J&x$HAZRtv- zsY;Hv(_z>Wd^fEG=%V?p3Eif;Gx#4qN^Bl($VQ?F769sXsZUNN<%F4}*&gIOetTuQ zWDx*lIc_Z678O&wSb2GeMi)gZgoLngGmlY3M$VTnIJ%0j#pTJ{y(FT{nB>q$fP)!q zm$nr53=+0l0?&-d2K9T6;Qs878L7>(?Ew1_9SZ|M%0Lo^QSY32PsL6)&Wr#Pf}@nd zpXqg0^mE^um~>YBqA%w_1oyeBv|sf#y)SckPtu{Tz)RE)txo1LD}L|+)$y`R*7k{( zj!uiQJh_}`ZOtj8@~D&Es*o6SkSP!KugL0Ws><#$33v)vFakP0Wy&x)4rFw=+6Yyh!R3wMABoE z2~_(#x73{(erq1BxTCe?cjrNALcE4_i7~F7_+ME+kbXNIMu$E6hDE;r4fEA1y%_!% z%p!nu_*ZIIg&>zj+4#l-jg?pNI`mAvHN8 zdV70^IB1d_q{jRKy{963c*o)QWP5u%C=qeY#M*H{ka`iDXcG8ocrd-Cte{$~>#W$r z+gm)?Dp)A8HJ0=Z94-grvZLd-VK!McG7bkTl%Sd>A(si`2&tCzxl90>(NrQ$P0`@s zpdby=DgxLytf6k5;>@O-%tKd%TmWxs9jh|q8oRp-YrO+T$;f*FhpkdfGP_n;DlvX( zl2_4h$-f}2HjAq$9@Km)+Ne72Czv+Q1yTwq6dbv9&pA0SFTa0sz^ltf=B+Phy=x{& z6Pzb(CBgpmxMR>^8l?HpJeS#d>mY3v{ryGQ+C(Cq5KI-g;7m>TW1|MDK=q=I9;#4N zSJ$_C@aLJy-}QBNng|6$-Y5u!)a|wxz<--opc-l8sfW|C(G*nxsUw8C$xEK@F?! z@op+eUqJq|(?VK#xVujf^->vWQ^aS|gtc>Wa+V}~q}7gd*h*0WLg{9-pDJ!$&Nt}U zVmpB#$J5Y7{Z0x>sKRWcFJpYJl&KfW`D!#3RS7Or}_ zVAC-okaG>*8#mfj{!H_eR9~2ajZ6O>Fr4)CgfijoxzSy0w6yr64F(=CAqBolwT%sJ z4b*Cx=Z9o;afJ^C$-AXyv*L%TC%%G$n(8HS$cF2$da`lwbUv2|N|H(=6O3Goh#=xX z;`(=)@;p+FF`I~Rcq2`sp`ii%QDM_T4DGnb3N5iV|IW`RZ!jvZuDk{N*h6^)1y=*j z1~F7^nWXoCc%8v&e0C4mbgZxEsABT+%q2BPfB9aaef0nvVDO89D!{&5^7S0l-3q}l za@6wAoIG{~Qi{im?$=ZEPFt-w=hpX`!$6`X>P;ncgV|J0Rp|5+^$H3K0y)Y~t3w4a>dGlC zC4L&BQA5u7e2x5W(~&X$je5Y{;yj&!c(;G%g>D9ti(MrejZW%cIY0NvecR$(YsqJg zpEc-^i-*VkiIRVJOo=Lx`>2b#P$LYv=2C0xj3@x!phx}oH|$u=bENWIzR7j z$bT-vkIRlz$qs8@B-i+vmXcEKLCJBwV$Y}CTJgjP-!EI>c5qTEqN3M!^kd1bO$Op? z>K&0KV#RvW2H=^3NUBKIP(Y>a=5Q$Ib0ZYz)e!(ys2r`? z6TA7_9RmrW`LD6gBB{ro=@|QCecz>lgS?gUlwaA=v;885MOC*#^;VCU9sks`!aLbu2MKMAH8wr#ej|`+zi)+`FY6pm%!>@D9tyP zr#!%k37IT;fD_?J%nbZR@iN9+yx`RP z`>|Rh|3Spdsjc60ao@m{Luhqs?Rq1*PrlUD>S3}^`eb>a$p3OyWmZY9E_a22cmwRt z$R8|KX++nH&#!@TgFt3;CFWBqk0MD7EU3(ZGrv{qR9aanAN}{}s3L>a?%wb4u#{od zgU;{{JnFfSTs+Ykqv|%=D=W}UX*MoR=r6CI;o~w81-(&g%bPGLR79c_xAbvN~7UW z_mzn?=)c(!u#n#g5M>z}bgis?-lCHA21dSodiv)`bcQFz523&wi&!C6z3mYJTDc@y zA8}N!G9AyhplXCc$_34vu*^J%u2}|3mxlnBz@|wp5BO7GvAx{%wDxY?{OT(ssajYw zGwO46DBwBZ5Tuch0=IBQ7l`7jTly;jv1`-4T!e9ER|1PxW>wjNPl%|aj>l^9_TJVo zX@R;D5uSU5au7w#lBw6G1iJ_(TN`&HB6`97b}byj;5 z@Sbgvo6icj`K-L-Q|WT6${rWJ&ntwW@Pg609*&;72uV+5Hcb<@Z!xZpy~I;O4xyB@ z-l$s=Ci6z<`=0zmS26@;36c`Z@yc+iaeds%c1E$RYh#O;vgHh-eO%I6d!{D`>i<%x zcfFiy2MX4VVr5~T^}}zhv9GV^4#_44MusbC?&Z$9j{B4a)sGlPk^$J}dJo%=dh%pc zM8))4-0Lr^)P)a1%xyPar?BQ*GYk&bj>{GnV(sNoh_>^hlqTsrqDn33N$^{^@Hw`Q z(=HYDt<~h3BlS_WHTGZpkGvZVt^Ou_{P%BL{rgI97irkccwwD2* zx{C4qqNT>Bo3-WTSBGG{#_aJU%Pq-GCJ$?Rz#d-%x9=xv`Qt>4w=ZuZVG#@+6GP_D z%11@=NouP`bg+t><$bxWPESbFZPTk$5w0!-`Lo264{!L4EobI zVss^UqH&b?aM!@IfP>!T{`UtstqMY;gLOzz+q*o>7-^R>=auBIo`b4EKFTXjtyibWyyx3yu6rURXLbjswxN|hQ+3V zu7pWb<|Puc>x9X++wsga5%~UG4)(yADlg|%eMty92zKY2P0@&V>A;(~t2g{LVp!EA z<1051HNyH6Cb6-_k>&sosMg7f*?aFgiHKJOJXCKok0a(Y?-FVQj1?ekP-aPLHmm9Iq#Ur*oN~3n?1j>I{XM|{)DaAc7a8I0kTRA)f`&5v%gC;%456Z_hMuJYF}D6T*H@%qa+pu18~P-w-~H#86r z4TeA!qM=*ZXwXrk7pgfa8~yX_>}+8*L0b@L9i-{@d>u_-Fj zq4w+*XFNe?IELfYH)a;#3=K8{KK_{|%B7Y*tlg`@wg(vD8X_rRa+EbHf9qcm@UQ@$ ztk40CO(!)ROZTZ@8)}6bpxdt6ren+w*sKI!WU}7i$!d5eC8%Fw3KI4IU0FfC$;F=3 z7Es6@1!z-?bUDKAQTZdW&-H3&*zU%s07OtIPmrOZDANP5?*Pkv|Su@4@A7LFeCa^`=Ne>#&z47cn~Edq72 zq5e!jO<@fU3Zp}Q7G5wnGGa~}1p3^_=dWgoOu?W7(z+s)1b>i+uo(V;rBI{yeYaxP zNELb<1VKFmSj`8;DLg>jTPo%zT#DfmQy$&A1>qm;>;{5&-j4w3aqIUP)2^MBE_*ES z*R^asUy1QQHGc|%8=TqZuaCTVL&3=<onTV%&c9v zLf|uyT}w;94Xy%`UscmIExmW^H2f~vWo9PlCv%)QzP$7T0Ryl2pq9AmjzB(t{`{6M zQ#hwmDMa@X0m0OJBc{0+90&BRJ&EZylrN@#6q+%yKEx+3eOH&feIPX7{$%dOQ)_^F zf!7SGTuqVd@7b@=-16LK90eQ8&7bcAN+S6%!wTVxzx2#p(aXgJs2}F#j|J%KjY}=J z@ituW#91yg%pc{l~LFbh<%rD#LJuP2)sWg!IQqPM#%oF%2x=rh_eq9)8>ntAf1**H|v25kryghT3t%w9I0oe0KC^4w4aG~P!-axpLOI7wn8 z|6zRUCx_#w2tJJA^$OhDRcva<(#5Pv`@ieo|KDzl{;#J4>>mL4Aw-t+19=byT_VIB zJUq|@|I^wbEO@rulO#(ACu+64JUp0=^efbo3dVq8d4=yUSU6qFQ!vX)&do@8u(;_m zFo9f)@mp;c`tV!BRnvzwt$z-A5{Fx|kyRRJySz77H|hO?e67H&cl|&F@dnQ!Y%zDClk`<9U)oUg%I8W|Nc}$CTvI(Xe30_Bij>{2DL19wZHv9n&cyoRCzYT}en}nM(m)D;m R(A!5p6y#K7i)0M_{|6b~EWrQ( literal 0 HcmV?d00001 diff --git a/Java/Picture/55.png b/Java/Picture/55.png new file mode 100644 index 0000000000000000000000000000000000000000..d35a9197d5e03ef14f0464c744b7e0da23f0d46b GIT binary patch literal 15695 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 Bn{)sG literal 0 HcmV?d00001 diff --git a/Java/Picture/JVMAbstractNeiCunModel.png b/Java/Picture/JVMAbstractNeiCunModel.png new file mode 100644 index 0000000000000000000000000000000000000000..0a08d75763c1babbd82c817e490913e79e4e9a20 GIT binary patch literal 13390 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,但内存操作实际发生的顺序却是:`A2->A1`。此时,处理器A的内存操作顺序被重排序了(处理器`B`的情况和处理器`A`一样,这里就不赘述了)。 + +这里的关键是,由于写缓冲区仅对自己的处理器可见,它会导致处理器执行内存操作的顺序可能会与内存实际的操作执行顺序不一致。由于现代的处理器都会使用写缓冲区,因此现代的处理器都会允许对写-读操做重排序。 + +为了保证内存可见性,`java`编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。`JMM`把内存屏障指令分为下列四类: + +|屏障类型 |指令示例| 说明| +|-------|-------|------| +|LoadLoad Barriers |Load1; LoadLoad; Load2| 确保Load1数据的装载,之前于Load2及所有后续装载指令的装载。| +|StoreStore Barriers |Store1; StoreStore; Store2 |确保Store1数据对其他处理器可见(刷新到内存),之前于Store2及所有后续存储指令的存储。| +|LoadStore Barriers |Load1; LoadStore; Store2 |确保Load1数据装载,之前于Store2及所有后续的存储指令刷新到内存。| +|StoreLoad Barriers |Store1; StoreLoad; Load2 |确保Store1数据对其他处理器变得可见(指刷新到内存),之前于Load2及所有后续装载指令的装载。| + +`StoreLoad Barriers`会使该屏障之前的所有内存访问指令(存储和装载指令)完成之后,才执行该屏障之后的内存访问指令。 +`StoreLoad Barriers`是一个“全能型”的屏障,它同时具有其他三个屏障的效果。现代的多处理器大都支持该屏障(其他类型的屏障不一定被所有处理器支持)。执行该屏障开销会很昂贵,因为当前处理器通常要把写缓冲区中的数据全部刷新到内存中(`buffer fully flush`)。 + +## `happens-before` + +从`JDK5`开始,`java`使用新的`JSR -133`内存模型(本文除非特别说明,针对的都是`JSR- 133`内存模型)。`JSR-133`提出了`happens-before`的概念,通过这个概念来阐述操作之间的内存可见性。如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在`happens-before`关系。这里提到的两个操作既可以是在一个线程之内,也可以是在不同线程之间。 与程序员密切相关的`happens-before`规则如下: + +- 程序顺序规则:一个线程中的每个操作,`happens- before` 于该线程中的任意后续操作。 +- 监视器锁规则:对一个监视器锁的解锁,`happens- before` 于随后对这个监视器锁的加锁。 +- `volatile`变量规则:对一个`volatile`域的写,`happens- before` 于任意后续对这`个volatile`域的读。 +- 传递性:如果`A happens- before B`,且`B happens- before C`,那么`A happens- before C`。 +注意,两个操作之间具有`happens-before`关系,并不意味着前一个操作必须要在后一个操作之前执行!`happens-before`仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前(`the first is visible to and ordered before the second`)。`happens- before`的定义很微妙,后文会具体说明`happens-before`为什么要这么定义。 + +`happens-before`与`JMM`的关系如下图所示: +![](Picture/55.png) +如上图所示,一个`happens-before`规则通常对应于多个编译器重排序规则和处理器重排序规则。对于`java`程序员来说,`happens-before`规则简单易懂,它避免程序员为了理解JMM提供的内存可见性保证而去学习复杂的重排序规则以及这些规则的具体实现。