线程安全三大特性简要概述

三大特性 原子、有序、可见

·1、从JMM内存模型来说,工作内存和主内存之间的数据同步需要靠volatile去保障可见性。确保访问时能从主内存中获取。

2、由于jvm指令重排导致的多线程访问时,产生数据不一致问题。例如:Object o = new Object()。对象创建过程中,将Objeict内存引用赋值给o和Object对象初始化赋值这两步就可能发生重排。试想象在多线程环境下,因指令重排,有线程将Objeict内存引用赋值给o,然后其他线程抢占到cpu,运行程序,此时发现o已经不为null,就去使用,而此时o实际还没有初始化完成。当再切回之前的线程后,继续完成初始化赋值,那么对于其他线程o的成员变量属性是变化的。

拿双重校验锁单例模式来讲:

synchronized虽然能保证synchronized中的代码能够在某个线程中执行完,再被其他线程访问,但是不能保证synchronized中的代码在执行时,其他线程访问单例对象。如果单例对象的创建发生指令重排,即使加了synchronized,那么在重排过程中,对单例对象的访问还是线程不安全的。
一旦我们加上volitate,避免了指令重排,那么就等于保证了在synchronized过程中,其他线程对单例对象的访问时,要么是null,要么就是初始化完成的对象。而不会说先拿到未初始化的对象,后又拿到已经初始化的对象。

public class Singleton {

    private volatile static Singleton instance;

    public static Singleton getInstance() {
        if (instance == null) {//避免指令重排后,这里访问单例对象要么是null继续等锁释放。要么就是初始化完成的对象return。
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

3、原子性,保证一段代码的执行是原子的,通常加锁实现,加锁后也就是一个线程访问锁中的代码时,其他线程需要阻塞等待锁释放

待完善...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值