Java多线程之线程的可见性(二)
来源:互联网 发布:mac韩服lol汉化 编辑:程序博客网 时间:2024/05/19 13:09
1.Java的内存模型
Java Memory Model (JAVA 内存模型)描述线程之间如何通过内存(memory)来进行交互。 具体说来, JVM中存在一个主存区(Main Memory或Java Heap Memory),对于所有线程进行共享,而每个线程又有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作并非发生在主存区,而是发生在工作内存中,而线程之间是不能直接相互访问,变量在程序中的传递,是依赖主存来完成的。
2、内存可见性
从上图可知,如果线程A对共享变量X进行了修改,但是线程A没有及时把更新后的值刷入到主内存中,而此时线程B从主内存读取共享变量X的值,所以X的值是原始值,那么我们就说对于线程B来讲,共享变量X的更改对线程B是不可见的。
例如:
public class NoVisibility{ private static boolean asleep = true; private static class readerThread extends Thread{ while(!asleep){ doSomething(); } } public static void main(String []args){ new readerThread().start(); asleep = false; }}
当主线程把asleep改成true时,这个new readerThread()可能会继续循环下去,因为主线程的asleep的结果储存在他的本地内存中,而没有刷新到主内存中,所以new readerThread()读取主内存,根本没有察觉到asleep的变化。
3.如何实现可见?
实现可见有四类关键字,volatile,java.util.concurrent中实现的原子操作类,synchronized,还有final
volatile
volatile赋予了变量可见——禁止编译器对成员变量进行优化,它修饰的成员变量在每次被线程访问时,都强迫从内存中重读该成员变量的值;而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存,这样在任何时刻两个不同线程总是看到某一成员变量的同一个值,这就是保证了可见性。简单来说就是读必须从主内存读,写必须写到主内存中。
由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。 就跟C中的一样 禁止编译器进行优化。
使用建议:
1.在上面的asleep状态变量的例子中,非常适合用volatile关键字,它用来检测某个状态变量以判断是否进行下一步操作。它常常用做中断或状态的标志。
2.当要访问的变量已在synchronized代码块中,或者为final时,不必使用。原因很简单,因为synchronized和final都能让变量可见。
synchronized
synchronized的可见性是由“对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store和write操作)”这条规则获得的。
Java.util.concurrent中实现的原子操作类
Java.util.concurrent中实现的原子操作类包括:
AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference。
其底层就是volatile和CAS 共同作用的结果:
- 首先使用了volatile 保证了内存可见性。
- 然后使用了CAS(compare-and-swap)算法 保证了原子性。
其中CAS算法的原理就是里面包含三个值:内存值A 预估值V 更新值 B 当且仅当 V == A 时,V = B; 否则,不会执行任何操作。
final
被final修饰的字段是构造器一旦初始化完成,并且构造器没有把“this”引用传递出去,那么在其它线程中就能看见final字段的值。
- Java多线程之线程的可见性(二)
- java多线程之可见性
- java 理解多线程及线程可见性
- java 理解多线程及线程可见性
- java多线程的可见性
- java多线程之共享变量的可见性、原子性
- Java多线程之可见性分析
- JAVA多线程——线程安全之原子性,有序性和可见性
- java多线程可见性
- Java线程可见性
- JAVA多线程的内存可见性
- Java多线程中内存的可见性
- java-多线程深入(二)互斥性和可见性
- 多线程的可见性
- java 线程(二)可见性与同步
- java 多线程基础之二:线程的中断(interrupt)
- [Java 多线程] 变量可见性
- Java多线程内存可见性
- 利用multiprocessing做进程间通信
- 基于机器学习的客流失预警分析
- angualrJs中$interpolate的运用
- spring-boot问题总结手册
- **c语言的预处理#,##的详细功能说明**
- Java多线程之线程的可见性(二)
- C6748_EDMA_SPI_FLASH
- AutoMapper官方文档(十五)【映射继承】
- java权限访问修饰符
- 装饰者设计模式
- 使用MongoTemplate管理MongoDB的一些查询操作(Java)
- Drawable基础知识总结----drawable标签selector的使用
- springmvc导入导出
- Ice与Corba之争(The Rise and Fall of CORBA)