java 多线程面试题
1.多线程的几种实现方式
2. volatile的原理,作用,能代替锁吗
保证可见性和有序性,不保证原子性
1.JMM内存模型
- Java内存模型(Java Memory Model简称JMM)是一种抽象的概念,并不真实存在,它描述的是一组规则或规范。
- 与JVM内存模型不同的是,JMM规定所有变量都存储在主内存,主内存是共享内存区域,所有的线程都可以访问。当线程有对这个变量有操作时,必须把这个变量从主内存复制一份到自己的工作空间中进行操作,操作完成后,再把变量写回主内存,不能直接操作主内存的变量。不同的线程无法访问其他线程的工作内存。
2.数据同步八大原子操作(硬件层面,cpu)
- (1)lock(锁定):作用于主内存的变量,把一个变量标记为一条线程独占状态
- (2)unlock(解锁):作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后 的变量才可以被其他线程锁定
- (3)read(读取):作用于主内存的变量,把一个变量值从主内存传输到线程的工作内存 中,以便随后的load动作使用
- (4)load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工 作内存的变量副本中
- (5)use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎
- (6)assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内 存的变量
- (7)store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存 中,以便随后的write的操作
- (8)write(写入):作用于工作内存的变量,它把store操作从工作内存中的一个变量的值 传送到主内存的变量中
3. 并发编程的三大特性
原子性
原子性指的是一个操作是不可中断的,即使在多线程环境下,一个操作一旦开始就不会被其他线程影响!
比如一个变量的++操作,代码中只有一行 i++,但在虚拟机底层并不是一步完成的,执行引擎最少需要经过赋值、自增1、写入工作内存等操作才完成,在这期间可能cpu被其他线程抢去,不能保证操作的原子性!一行代码已经如此,更何况真实开发的几十行代码更有原子性问题!
可见性
可见性指的是当一个线程修改了某个共享变量的值,其他线程能够马上感知到这个修改的值。
对于单线程来说,串行不存在可见性问题。对于多线程来说,由于不同线程对共享变量的操作都是在自己的工作内存中执行,这就可能存在 :线程A在自己的工作内存中修改了共享变量x的值,还没来得及写回主内存中,线程B把主内存中原来的值又加载到自己的工作内存中进行操作,线程A对共享变量的操作对线程B来说不可见,这种工作内存与主内存同步的延迟现象就造成了可见性问题!另外指令重排以及编译器优化也可能导致可见性问题
有序性
有序性即程序执行的顺序是否按照代码的先后顺序执行。对于单线程来说,可以认为代码是按照顺序执行的,所有操作都视为有序行为。