Hi,大家好,我是Mic
一个工作了4年的小伙伴,遇到了一个非常抽象的面试题,说说你对线程安全性的理解。
这类问题,对于临时刷面试题来面试的小伙伴,往往是致命的。
一个是不知道从何说起,也就是语言组织比较困难。
其次就是,如果对于线程安全性没有一定程度的理解,一般很难说出你的理解。
ok,我们来看看这个问题的回答。
部分高手面试文档已整理,需要的小伙伴可以扫描添加下方二维码
普通人:
嗯..................................
高手:
简单来说,在多个线程访问某个方法或者对象的时候,不管通过任何的方式调用以及线程如何去交替执行。
在程序中不做任何同步干预操作的情况下,这个方法或者对象的执行/修改都能按照预期的结果来反馈,那么这个类就是线程安全的。
实际上,线程安全问题的具体表现体现在三个方面,原子性、有序性、可见性。
原子性呢,是指当一个线程执行一系列程序指令操作的时候,它应该是不可中断的,因为一旦出现中断,站在多线程的视角来看,这一系列的程序指令会出现前后执行结果不一致的问题。
这个和数据库里面的原子性是一样的,简单来说就是一段程序只能由一个线程完整的执行完成,而不能存在多个线程干扰。
CPU的上下文切换,是导致原子性问题的核心,而JVM里面提供了Synchronized关键字来解决原子性问题。
可见性,就是说在多线程环境下,由于读和写是发生在不同的线程里面,有可能出现某个线程对共享变量的修改,对其他线程不是实时可见的。
导致可见性问题的原因有很多,比如CPU的高速缓存、CPU的指令重排序、编译器的指令重排序。
有序性,指的是程序编写的指令顺序和最终CPU运行的指令顺序可能出现不一致的现象,这种现象也可以称为指令重排序,所以有序性也会导致可见性问题。
可见性和有序性可以通过JVM里面提供了一个Volatile关键字来解决。
在我看来,导致有序性、原子性、可见性问题的本质,是计算机工程师为了最大化提升CPU利用率导致的。比如为了提升CPU利用率,设计了三级缓存、设计了StoreBuffer、设计了缓存行这种预读机制、在操作系统里面,设计了线程模型、在编译器里面,设计了编译器的深度优化机制。
一上就是我对这个问题的理解。
总结
从高手的回答中,可以很深刻的感受到,他对于计算机底层原理和线程安全性相关的底层实现是理解得很透彻的。
对我来说,这个人去写程序代码,不用担心他滥用线程导致一些不可预测的线程安全性问题了,这就是这个面试题的价值。
本期的普通人VS高手面试系列就到这里结束了,喜欢的朋友记得点赞和收藏。
另外,这些面试题我都整理成了笔记,大家有需要的可以私信获取。
部分高手面试文档已整理,需要的小伙伴可以扫描添加下方二维码
↓↓↓↓↓↓↓↓