java并发编程实战:对象的共享笔记

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/sxj159753/article/details/78599118

可见性

volatile关键字:
http://www.cnblogs.com/paddix/p/5428507.html

volatile关键字的两层语义:
- 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
- 禁止进行指令重排序。

volatile只能保证对单次读/写的原子性
volatile不能保证 i++ 这种的原子性。

使用场景:
双重检查(DCL)单例

package com.paddx.test.concurrent;

public class Singleton {
    public static volatile Singleton singleton;

    /**
     * 构造函数私有,禁止外部实例化
     */
    private Singleton() {};

    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (singleton) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

现在我们分析一下为什么要在变量singleton之间加上volatile关键字。要理解这个问题,先要了解对象的构造过程,实例化一个对象其实可以分为三个步骤:
- (1)分配内存空间。
- (2)初始化对象。
- (3)将内存空间的地址赋值给对应的引用。

但是由于操作系统可以对指令进行重排序,所以上面的过程也可能会变成如下过程:
- (1)分配内存空间。
- (2)将内存空间的地址赋值给对应的引用。
- (3)初始化对象

  如果是这个流程,多线程环境下就可能将一个未初始化的对象引用暴露出来,从而导致不可预料的结果。因此,为了防止这个过程的重排序,我们需要将变量设置为volatile类型的变量。
  
状态标记量

volatile boolean inited = false;
//线程1:
context = loadContext();  
inited = true;            
 
//线程2:
while(!inited ){
sleep()
}
doSomethingwithconfig(context);

http://www.importnew.com/18126.html

发布与逸出

发布:使对象能够在除当前作用域之外的地方使用。
- 将对象的引用存储到公共静态域。
- 在非私有方法中返回引用。
- 不要在构造过程中使this引用逸出。

**构造方法使用匿名内部类会产生溢出。**

使用工厂方法来防止。

溢出:指某个对象不应该发布却被发布了。

线程封闭

多线程访问共享数据时,通常需要同步,一种避免使用同步的方式就是不共享数据。如果仅在单线程里访问数据,那么就不需要使用同步,这种技术被称为线程封闭。

栈封闭

局部变量访问对象。

ThreadLocal

http://blog.csdn.net/cauchyweierstrass/article/details/48001521

不变性

不可变对象一定是线程安全的。

对于如何构建一个不可变对象,我们有三个条件(虽然说是”条件”,但并不是那么硬性的,可以算是某种建议):
- 对象创建后保证状态不可变
- 对象的所有field都是final
- 创建期间没有逸出自身引用(this引用逸出),保证对象的创建正确。

https://www.cnblogs.com/Kavlez/p/4041395.html

不可变对象与初始化安全性

猜你喜欢

转载自blog.csdn.net/sxj159753/article/details/78599118