diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 53c59fab..50a18405 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -128,6 +128,18 @@ public InitialOrderTest() { 5. 子类(实例变量、普通语句块) 6. 子类(构造函数) +**5. 静态内部类** + +内部类的一种,静态内部类不依赖外部类,且不能访问外部类的非 static 变量和方法。 + +**6. 静态导包** + +```source-java +import static com.xxx.ClassName.* +``` + +在使用静态变量和方法时不用再指明 ClassName,从而简化代码,但可读性大大降低。 + # 二、Object 通用方法 ## 概览 diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 3b679cd0..742d6408 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -1061,13 +1061,13 @@ Java 内存模型定义了 8 个操作来完成主内存和工作内存的交互 ### 1. 原子性 -Java 内存模型允许虚拟机将没有被 volatile 修饰的 64 位数据(long,double)的读写操作划分为两次 32 位的操作来进行,也就是说对这部分数据的操作可以不具备原子性。 +Java 内存模型保证了 read、load、use、assign、store、write、lock 和 unlock 操作具有原子性,例如对一个 int 类型的变量执行 assign 赋值操作,这个操作就是原子性的。但是 Java 内存模型允许虚拟机将没有被 volatile 修饰的 64 位数据(long,double)的读写操作划分为两次 32 位的操作来进行,即 load、store、read 和 write 操作可以不具备原子性。 有一个错误认识就是,int 等原子性的变量在多线程环境中不会出现线程安全问题。前面的线程不安全示例代码中,cnt 变量属于 int 类型变量,1000 个线程对它进行自增操作之后,得到的值为 997 而不是 1000。 为了方便讨论,将内存间的交互操作简化为 3 个:load、assign、store。 -下图演示了两个线程同时对 cnt 变量进行操作,load、assign、store 这一系列操作不具备原子性,那么在 T1 修改 cnt 并且还没有将修改后的值写入主内存,T2 依然可以读入该变量的值。可以看出,这两个线程虽然执行了两次自增运算,但是主内存中 cnt 的值最后为 1 而不是 2。因此对 int 类型读写操作满足原子性只是说明 load、assign、store 这些单个操作具备原子性。 +下图演示了两个线程同时对 cnt 变量进行操作,load、assign、store 这一系列操作整体上看不具备原子性,那么在 T1 修改 cnt 并且还没有将修改后的值写入主内存,T2 依然可以读入该变量的值。可以看出,这两个线程虽然执行了两次自增运算,但是主内存中 cnt 的值最后为 1 而不是 2。因此对 int 类型读写操作满足原子性只是说明 load、assign、store 这些单个操作具备原子性。