一、非原子的64位操作:

  当线程在没有同步的情况下读取变量时,可能会得到一个失效值,但至少这个值是由之前某个线程设置的值,而不是一个随机值,这种安全性保证被称为最低安全性。最低安全性适用于绝大多数变量,但存在一个例外:非volatile类型的64位数值变量(double,long),Java内存模型要求,变量的读取和写入操作都必须是原子操作,但对于非volatile型的long,double变量,JVM允许将64位的读操作或写操作分解为两个32位的操作,当读取一个非volatile类型的long变量时,如果对该变量的读操作和写操作在不同的线程中执行,那么很可能会读取到某个值的高32位和另一个值的低32位。

  因此,即使不考虑失效数据问题,在多线程中使用共享且可变的long,double等类型的变量也是不安全的,除非用关键字volatile来声明它们,或者用锁保护起来。

二、volatile变量

  当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量时共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。
  volatile局限在于:它通常用于某个操作完成、发生中断或者状态的标志,其语义不足以确保递增操作的原子性,除非你能确保只有一个线程对变量执行写操作。
  当且仅当满足以下条件时,才应该使用volatile变量:
  1)对变量的写入操作不依赖变量的当前值,或者能确保只有单个线程更新变量的值;
  2)该变量不会与其他状态变量一起纳入不变性条件中;
  3)在访问变量时不需要加锁。

  加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性。

三、对象的发布逸出

如下示例代码:

public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener{
new EventListener()(){
public void onEvent(Event e){
doSomething(e);
}
}
}
}
}

  这个类不是安全的,因为当ThisEscape发布EventListener时,也隐含的发布了ThisEscape实例本身,因为这个内部类的实例中包含了对ThisEscape实例的隐含应用,因此,当从对象的构造函数中发布对象时,只是发布了一个尚未构造完成的对象。即使发布对象的语句位于构造函数的最后一行也是如此。在构造函数中创建线程并没有错误,但最好不要立即启动它,而是通过一个start或initialize方法来启动,例如,可通过如下工厂方法来防止this引用在构造过程中逸出:

public class SafeListener {
private static final EventListener listener;
public SafeListener() {
listener = new EventListener() {
public void onEvent(Event e){
doSomeThing(e);
}
}
}
public static SafeListener newInstance(EventSource source){
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}

  

最新文章

  1. 使用curl进行https请求
  2. windows下CMake使用图文手册 Part 1
  3. C语言运算符优先级和口诀(转)
  4. 深入浅出C#中的静态与非静态
  5. CSS高级知识
  6. 递推DP URAL 1225 Flags
  7. 转:简单的Mysql主从复制设置
  8. Node入门教程(4)第三章:第一个 Nodejs 程序
  9. iOS 类方法 、野指针与空指针
  10. HTTPS加密那点事-对称、非对称加密、数字证书
  11. xml 转换成对象(采用反射机制对对对象属性赋值)
  12. 利用ENVI FX从RGB提取建筑物轮廓
  13. 【非专业前端】vue+element+webpack
  14. kafka集群的错误处理--kafka一个节点挂了,导致消费失败
  15. XPath简介及节点
  16. dict的items()方法于iteritems()方法的不同
  17. 【架构师之路】Nginx负载均衡与反向代理—《亿级流量网站架构核心技术》
  18. 结合领域驱动设计的SOA分布式软件架构
  19. mysql通过“延迟关联”进行limit分页查询优化的一个实例
  20. 静默安装oracle 11g,环境预检查时报错,SEVERE: [FATAL] PRVF-0002 : 无法检索本地节点名

热门文章

  1. 整理C++面试题for非CS程序猿——更新至【48】
  2. beef配合ettercap批量劫持内网的浏览器
  3. JavaProblem之hashCode详解
  4. AtCoder Grand Contest 015
  5. 51 nod 1211 数独 DLX
  6. bzoj:3085: 反质数加强版SAPGAP
  7. HDU1016(素数环)
  8. Cup(二分)
  9. c++extern关键字详解
  10. JAVA爬虫实践(实践四:webMagic和phantomjs和淘宝爬虫)