2024年《Java高并发编程详解:多线程与架构设计》笔记(三,2024最新Golang高频精选面试题分享

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 工作内存和Java内存模型一样是抽象的概念,它并不存在,它涵盖了缓存、寄存器、编译器优化以及硬件等。

并发编程的三个重要特性

  • 原子性:事务内所有的操作要么都执行要么都不执行。
  • 可见性:当一个线程对共享变量进行了修改,那么另外的线程可以立即看到修改后的值。
  • 有序性:程序代码在执行过程中的先后顺序。

JVM如何保证三大特性

在多线程的情况下,如果不能保证三大特性可能会出现错误。JVM采用内存模型的机制来屏蔽各个平台和操作系统之间内存访问的差异,以实现让Java程序在各个平台下达到一致的内存访问效果,比如C语言中的整型变量,在某些平台下占用了两个字节的内容,在某平台下则占用了四个字节的内容,Java在任何平台下int类型就是四个字节,这就是一致内存访问效果。

JMM与原子性:Java内存模型只保证了基本读取和赋值的原子性操作,其他的均不保证,如自增。

JMM与可见性:volatile关键字、synchronized关键字和JUC提供的显式锁这三种方式都可以保证可见性的语义。

JMM与有序性:Java内存模型中,允许编译器和处理器对指令进行重排序,上面的三种方式也都可以保证有序性。另外Java内存模型具备一些天生的有序性规则(Happens-before原则)。

happens-before原则:

  • 程序次数规则:在一个线程内,代码按照编写时的次序执行。
  • 锁定规则:一个unlock操作要先行发生于对同一个锁的lock操作。
  • volatile变量规则:对一个变量的写操作要早于对这个变量的读操作。
  • 传递规则:如果操作A先于操作B且操作B先于操作C,则操作A肯定先于操作C,说明happends-before原则具备传递性。
  • 线程启动规则:Thread对象的start方法先行发生于对线程的任何动作。
  • 线程中断规则:对线程执行interrupt方法肯定优先于捕获到中断信息。
  • 线程的终结规则:线程中所有的操作都要先行发生于线程的终止检测。
  • 对象的终结规则:一个对象初始化的完成先行发生于finalize方法之前。

volatile的原理和实现机制

volatile可以确保可见性和顺序性,到底如何实现的呢?我们可以通过OpenJDK下的unsafe.cpp源码看到被volatile修饰的变量存在于一个“lock;”的前缀,该前缀实质上相当于一个内存屏障,该内存屏障会为指令的执行提供下面几个保障。

  • 确保指令重排序时不会将其后面的代码排到内存屏障之前。
  • 确保指令重排序时不会将其前面的代码排到内存屏障之后。
  • 确保在执行到内存屏障修饰的指令时前面的代码必须全部执行完成。
  • 强制将线程工作内存中值的修改刷新至主内存中。
  • 如果是写操作,则导致其他线程工作内存(CPU Cache)中的缓存数据失效。

volatile使用场景

  1. 开关控制(利用可见性特点)。
  2. 状态标记(利用顺序性特点)。
  3. Singleton设计模式的double-check(利用顺序性特点)。

volatile和synchronized区别

  1. volatile关键字只能用于修饰实例变量或者类变量,不能用于修饰方法以及方法参数和局部变量、常量等。
  2. synchronized关键字不能用于对变量的修饰,只能用于修饰方法或者语句块。
  3. volatile修饰的变量可以为null,synchronized关键字同步语句块的monitor对象不能为null。
  4. synchronized关键字能保证原子性,而volatile无法保证。(原子性)
  5. synchronized关键字借助于JVM指令的monitor enter和moniter exit使得同步代码串行化,在monitor exit时所有共享资源都会被刷新到主内存中。(可见性)
  6. volatile使用机器指令(偏硬件)“.lock;”的方式迫使其他线程工作内存中的数据失效,不得不到主内存中进行再次加载。(可见性)
  7. volatile关键字禁止JVM编译器以及处理器对其进行重排序。(有序性)
  8. synchronized关键字是以程序的串行化执行来保证有序性。(有序性)
  9. volatile不会使线程陷入阻塞,synchronized关键字会使线程进入阻塞。

7种单例设计模式

前面有一篇文章也提到了设计模式,这里主要讲的是单例模式。

  1. 饿汉式:实例instance初始化收集进方法中,在多线程情况下不可能被实例化两次。
  2. 懒汉式:使用实例instance的时候再去创建,但是在多线程下无法保证单例的唯一性。
  3. 懒汉式+同步方法:在懒汉式基础上给getInstance方法加上synchronized关键字,保证数据同步性。
  4. Double-Check:定义未被初始化的实例,然后在实例首次初始化时加锁,但是无法保证实例化的有序性。
  5. Volatile+Double-Check:对未被初始化的实例加上volatile关键字保证有序性。
  6. Holder方式:实例放到静态内部类Holder之中,实例的创建过程在Java程序编译时期收集至方法,目前是使用最广的设计模式之一。
  7. 枚举方法:枚举类型不允许继承,同样是线程安全且只能被实例化一次。

Holder单例模式代码:

public class HolderSingleton {
    public HolderSingleton() {
    }

    static class Holder {
        private static final HolderSingleton instance = new HolderSingleton();
    }

    public static final HolderSingleton getInstance() {
        return Holder.instance;
    }

}

枚举单例模式代码:



![img](https://img-blog.csdnimg.cn/img_convert/0ec757e61680779ace348969255440b3.png)
![img](https://img-blog.csdnimg.cn/img_convert/9ed8111552b201da76997add8a26945c.png)
![img](https://img-blog.csdnimg.cn/img_convert/92bc5dfdb9846d0b8ff94d7893682627.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**


**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**

  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值