对象的共享
Posted changlili
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对象的共享相关的知识,希望对你有一定的参考价值。
对象的共享
要编写正确的并发程序,关键在于:在访问共享的可变状态时需要进行正确的管理。
1.可见性
为了确保多个线程之间对内存写入操作的可见性,必须使用同步机制。
重排序: 多个线程操作的时候没有按照程序的定义的顺序来执行。只要在某个线程中无法检测到重排序的情况,那么就无法确保线程中的操作按照程序中指定的顺序来执行。
2.失效数据
a, 缺乏同步的程序中可能产生错误失效数据。
b,最低安全性:线程在没有同步情况下读取变量值,得到一个失效值,但这个值是由之前某个线程设置的值,而不是随机值,这种安全保证称为最低安全性。
c,非原子操作64位:非volatile类型的long和double变量,JVM允许将64位的读操作和写操作分解为两个32位的原子操作,若读取一个非voltatile类型的long变量时,如果该变量读和写不在同一个线程中执行,那么可能读到高32和低32位。在多线程中使用共享且可变的long,double等类型变量也是不安全的,除非使用volatile,或者使用锁。
d,加锁与可见性
当线程B执行由锁保护的同步代码时,可以看见线程A之前在同一个同步代码块中所有的所有操作。如果没有同步,就无法保证。
e,voltatile变量
volatitle: 用来确保将变量的更新操作通知到其他线程,把变量声明为volatile,编译时与运行时都会注意到这个变量是共享的,因此不会将变量上的操作与其他内存操作一起重排,volatile变量不会被缓存在寄存器或者其他处理器看不见的地方,因此volatile变量总会返回最新写入的值。
从内存可见性的角度来看,写入volatile变量相当于退出同步代码块,读取volatile变量相当于退出同步代码块。
仅当volatile变量能简化代码的实现及对同步策略的验证时,才应使用。如果在验证正确性进行复杂判断就不要使用volatile变量。
volatile变量的正确使用方式包括:确保他们自身状态的可见性,确保所引用对象的状态的可见性,以及标识一些重要的程序生命周期事件的发生(如:初始化和关闭)。
加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性。
满足一下所有条件时,才应使用volatitle变量:
a, 对变量的写入操作不依赖变量当前值,或者确保只有单个线程更新变量值。
b, 该变量不会与其他状态变量一起纳入不变性条件。
c, 在访问变量时不需要加锁。
3,发布与逸出
发布一个对象:使对象能够在当前作用域之外的代码中使用;在某个非私有的方法中返回该引用,或者将引用传递到其他类中。
常见做法:将对象的引用保存到一个共有静态变量中,以便任何类和线程都能看到该对象。
间接发布对象
封装能够使得对程序的正确性进行分析变得可能,并使得无意中破坏设计约束条件变得更难。
逸出:当某个不应该发布的对象被发布时。
4,安全的对象构造过程
不要在构造过程中使用this引用逸出。
以上是关于对象的共享的主要内容,如果未能解决你的问题,请参考以下文章