对象的共享

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引用逸出。

 



以上是关于对象的共享的主要内容,如果未能解决你的问题,请参考以下文章

将共享对象链接到其他共享对象 C++ 项目

从另一个共享对象动态加载共享对象时的约束?

对象的使用和共享:ThreadLocal

在进程之间共享一个复杂的对象?

指向共享对象的指针在拥有它的不同对象中是不同的

多个线程访问共享对象和数据的方式