内存一致性错误(Memory Consistency Errors)
2016-07-03 23:25
585 查看
内存一致性错误发生在当不同的线程本对相同数据有不一致的视角。造成内存一致性错误的原因很复杂,不在本教程的范围之内。幸运的是,程序员不需要了解造成这个问题的详细原因,所需要的是一个策略来避免它们的发生。
避免内存一致性错误发生的关键是理解现行发生关系。这个关系是一个简单的保证,内存被一个操作时,对另外一个操作是可见的。为了证明这个,设计如下一个例子,假设定义一个简单int类型字段并初始化:
变量counter被两个线程共享,A和B,假设线程A对counter自增:
同时,紧随其后,线程B打印出变量counter:
要是两个语句是在同一个线程中被执行的,那结果是安全的,被打印出来的值就是1.但是,如果这两个语句在不同的线程中执行,那打印出来的值将可能是0,因为不能保证线程A对counter的改变对线程B是可见的,除非程序员已经在这两个语句中将现行发生关系建立起来。
有多种方式创建现行发生关系。其中一种方式是使用synchronization,我们将会在接下来的下一节中看到。
我们已经看过两种方式创建现行发生关系。
当一个语句调用Thread.start,每个和这个语句有现行发生关系的语句同样和被新线程执行的语句有现行发生关系。这代码的结果是新创建的线程对新线程是可见的。
当一个线程终止并且引发一个Thread.join发生在另外一个线程的返回,那么,所有被终止线程执行的语句和所有成功join的语句是有现行发生关系的,这代码的结果是线程执行join对另外一个线程是可见的。
如期望了解创建现行发生关系的方法有哪些,请查阅
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility
避免内存一致性错误发生的关键是理解现行发生关系。这个关系是一个简单的保证,内存被一个操作时,对另外一个操作是可见的。为了证明这个,设计如下一个例子,假设定义一个简单int类型字段并初始化:
int counter = 0;
变量counter被两个线程共享,A和B,假设线程A对counter自增:
counter++;
同时,紧随其后,线程B打印出变量counter:
System.out.println(counter);
要是两个语句是在同一个线程中被执行的,那结果是安全的,被打印出来的值就是1.但是,如果这两个语句在不同的线程中执行,那打印出来的值将可能是0,因为不能保证线程A对counter的改变对线程B是可见的,除非程序员已经在这两个语句中将现行发生关系建立起来。
有多种方式创建现行发生关系。其中一种方式是使用synchronization,我们将会在接下来的下一节中看到。
我们已经看过两种方式创建现行发生关系。
当一个语句调用Thread.start,每个和这个语句有现行发生关系的语句同样和被新线程执行的语句有现行发生关系。这代码的结果是新创建的线程对新线程是可见的。
当一个线程终止并且引发一个Thread.join发生在另外一个线程的返回,那么,所有被终止线程执行的语句和所有成功join的语句是有现行发生关系的,这代码的结果是线程执行join对另外一个线程是可见的。
如期望了解创建现行发生关系的方法有哪些,请查阅
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树