Java并发(四)——synchronized、volatile

synchronized、volatile

1 Java内存模型JMM

在这里插入图片描述

所有共享变量都存储在主存中,每个线程都保存了一份该变量的副本

2 伪共享

Cache内部是按行存储的,Cache行大小一般为2的幂次数字节

由于每次从主存中复制变量到Cache中的是内存块(局部性原理),而不是单个变量,就存在一个Cache行中有多个变量,当多线程操作的时候同一个Cache行里的不同变量时,性能会下将,这就是伪共享

通过填充字段来填充该变量所在的Cache行

3 指令重排

每个指令包含多个步骤,每个步骤可能使用不同的硬件,指令重排对于提高CPU处理性能十分必要,虽然由此带来乱序的问题,但是这点牺牲是值得的

指令重排一般分类:

  • 编译器优化重排:编译器在不改变单线程程序语义的前提下,重新安排
  • 指令并行重排:现代处理器采用了指令级并行技术。在不存在数据依赖性前提下,重新安排
  • 内存系统重排:由于处理器使用缓存和读写缓冲区,导致内存与缓存的数据同步存在时间差

指令重排可以保证串行语义一致,但是没有义务保证多线程间的语义一致

JMM提供了happens-before规则,只要不改变程序的执行结果(单线程或者正确同步的多线程),编译器和处理器怎么优化都行

如果操作A happens-before 操作B,那么操作A在内存上所作的操作对操作B都是可见的,不管他们在不在一个线程

4 synchronized

synchronized块是Java 提供的一种原子性内置锁、同步锁、监视器锁

线程的执行代码在进入synchronized代码块前会自动获取内部锁,这时候其他线程访问该同步代码块时会被阻塞挂起

拿到内部锁的线程会在正常退出同步代码块或者抛出异常后或者在同步块内调用了该内置锁资源的wait系列方法时释放该内置锁

synchronized的内存语义:将synchronized块使用到的变量从线程的工作内存中删除,直接从主存中获取;退出synchronized块时,将变量的修改刷新到主存

构造方法不能修饰synchronized

synchronized可用来标记

  • 静态方法,使用当前类作为锁
  • 普通方法,使用当前实例作为锁
  • 代码块,使用某个变量作为锁
synchronized void method() {
  //业务代码
}

synchronized static void method() {
//业务代码
}

synchronized(this) {
  //业务代码
}
// 双重校验的单例模式
public class Singleton {

    private volatile static Singleton uniqueInstance;

    private Singleton() {
    }

    public  static Singleton getUniqueInstance() {
       //先判断对象是否已经实例过,没有实例化过才进入加锁代码
        if (uniqueInstance == null) {
            //类对象加锁
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

5 volatile

当变量被声明为volatile时,则不会从线程的工作内存获取该变量,会直接从主存中获取

保证了并发的可见性,但并不保证操作的原子性

标记为volatile也可以避免指令重排

6 synchronized和Lock

synchronizedLock
关键字
依赖于JVM靠JDK实现的
执行完或发生异常,自动释放锁需要在finally中手动释放锁
可重入锁可重入锁
等待不可中断等待可中断
非公平公平、非公平
默认使用Object的wait/notify方法可以使用Condition的await/signal方法,唤醒指定线程

7 synchronized和volatile

synchronizedvolatile
修饰方法、代码块只能作用于变量
可见性、原子性只能保证可见性
主要解决资源访问的同步性主要解决变量访问的可见性
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值