Java多线程与并发基础 (3)

1.是一组规范,需要JVM实现遵守这个规范,以便实现安全的多线程程序
2.volatile、synchronized、Lock等同步工具和关键字实现原理都用到了JMM
3.重排序、内存可见性、原子性

面试题10:什么是happens-before,规则有哪些

解决可见性问题的:在时间上,动作A发生在动作B之前,B保证能看见A,这就是happens-before

规则

1 单线程按代码顺序规则;2 锁操作(synchronized和Lock);3volatile变量;4.JUC工具类的Happens-Before原则

5.线程启动时子线程启动前能看到主线程run的所有内容;6.线程join主线程一定要等待子线程完成后再去做后面操作

7.传递性 8.中断检测 9.对象构造方法的最后一行指令 happens-before 于 finalize() 方法的第一行指令

面试题11:讲一讲volatile关键字

volatile是一种同步机制,比synchronized或者Lock相关类更轻量,因为使用volatile并不会发生上下文切换等开销很大的行为。而加锁时对象锁会阻塞开销大。

可见性,如果一个变量别修饰成volatile,那么JVM就知道了这个变量可能会被并发修改;

不能保证原子性

面试题12:volatile的适用场合及作用

作用

1.保证可见性 2.禁止指令重排序(单例双重锁时)

适合场景

适用场合1:boolean flag,布尔具有原子性,可再由volatile保证其可见性

适用场合2:作为刷新之前变量的触发器

但不适合非原子性操作如:a++等

面试题13:volatile和synchronized的异同

1 性能开销方面: 锁开销更大,volatile无加锁阻塞开销
2 作用方面:volatile只能保证可见性,锁既能保证可见性,又能保证原子性

面试题14:什么是内存可见性问题,为什么存在

多线程下,一个线程修改共享数据后,其它线程能否感知到修改了数据的线程的变化

CPU有多级缓存,导致读的数据过期,各处理机有独自的缓存未及时更新时,与主存内容不一致

面试题15:主内存和本地内存的关系是什么

Java 作为高级语言,屏蔽了CPU cache等底层细节,用 JMM 定义了一套读写内存数据的规范,虽然我们不再需要关心一级缓存和二级缓存的问题,但是,JMM 抽象了主内存和本地内存的概念。

线程拥有自己的本地内存,并共享主内存的数据;线程读写共享数据也是通过本地内存交换的,所以才导致了可见性问题。

面试题16:什么是原子操作,Java的原子操作有哪些

原子操作

一系列的操作,要么全部执行成功,要么全部不执行,不会出现执行一半的情况,是不可分割的。

1)除long和double之外的基本类型(int, byte, boolean, short, char, float)的"赋值操作"

2)所有"引用reference的赋值操作",不管是 32 位的机器还是 64 位的机器

3)java.concurrent.Atomic.* 包中所有类的原子操作

面试题17:long 和 double 的原子性你了解吗

在32位上的JVM上,long 和 double的操作不是原子的,但是在64位的JVM上是原子的。

在32位机器上一次只能读写32位;而浮点数、long型有8字节64位;要分高32位和低32位两条指令分开写入,类似汇编语言浮点数乘法分高低位寄存器;64位不用分两次读写了

面试题18:生成对象的过程是不是原子操作

不是,对象生成会生成分配空间、初始化、赋值,三条指令,有可能会被重排序,导致空指针

面试题19:区分JVM内存结构、Java内存模型 、Java对象模型

Java内存模型,和Java的并发编程有关

详见面试题9

JVM内存结构,和Java虚拟机的运行时区域(堆栈)有关

堆区、方法区(存放常量池 引用 类信息)
栈区、本地方法栈、程序计数器

Java对象模型,和Java对象在虚拟机中的表现形式有关

是Java对象自身的存储模型,在方法区中Kclass类信息(虚函数表),在堆中存放new实例,在线程栈中存放引用,OOP-Klass Model

面试题20:什么是重排序

指令实际执行顺序和代码在java文件中的顺序不一致

重排序的好处:提高处理速度,包括编译器优化、指令重排序(局部性原理)

死锁 面试题1:写一个必然死锁的例子

synchronized嵌套,构成请求循环

面试题2:生产中什么场景下会发生死锁

并发中多线程互不相让:当两个(或更多)线程(或进程)相互持有对方所需要的资源,又不主动释放,导致所有人都无法继续前进,导致程序陷入无尽的阻塞,这就是死锁。

面试题3:发生死锁必须满足哪些条件

1.互斥

2.请求和保持

3.不可剥夺

4.存储循环等待链

面试题4:如何用工具定位死锁

1.jstack命令在程序发生死锁后,进行堆栈分析出死锁线程

2.ThreadMXbean 程序运行中发现死锁,一旦发现死锁可以让用户去打日志

面试题5:有哪些解决死锁问题的策略

1.死锁语法,不让死锁发生

破坏死锁的四个条件之一;如:哲学家换手、转账换序

2.死锁避免

银行家算法、系统安全序列

3.死锁检查与恢复

适用资源请求分配图,一段时间内检查死锁,有死锁就恢复策略,采用恢复策略;

恢复方法:进程终止 、资源剥夺

4.鸵鸟策略(忽略死锁)

先忽略,后期再让人工恢复

面试题6:死锁避免策略和检测与恢复策略的主要思路是什么

死锁语法

破坏死锁的四大条件之一

死锁避免

找到安全序列,银行家算法

死锁检测与恢复

资源请求分配图

面试题7:讲一讲经典的哲学家就餐问题,如何解决死锁

什么时候死锁

哲学家各拿起自己左手边的筷子,又去请求拿右手边筷子循环请求时而阻塞

如何解决死锁

1.一次两只筷子,形成原子性操作

2.只允许4个人拿有筷子

面试题8:实际开发中如何避免死锁

设置超时时间

多使用并发类而不是自己设计锁

尽量降低锁的使用粒度:用不同的锁而不是一个锁,锁的范围越小越好

避免锁的嵌套:MustDeadLock类

分配资源前先看能不能收回来:银行家算法

尽量不要几个功能用同一把锁:专锁专用

给你的线程起个有意义的名字:debug和排查时事半功倍,框架和JDK都遵守这个最佳实践

面试题9:什么是活跃性问题?活锁、饥饿和死锁有什么区别

活锁

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpgwfd.html