一、如何理解线程安全
在多线程中稍微不注意就会出现线程安全问题,那么什么是线程安全问题?
在深入理解Java虚拟机一书中看到的定义时
在多线程条件下,多个线程肯定会相互协作完成一件事,一般来说就会涉及到多个线程将相互通信告知彼此状态以及当前执行结果等,另外为了性能优化,还会涉及到编辑器指令重排序和处理器指令重排序
二、并发编程中的主要解决哪两个问题
1、线程之间如何通信
通信是指线程之间以何种机制来交换信息,主要有两种:共享内存和消息传递
2、线程之间如何完成同步(这里的线程指的是并发执行的活动实体)
Java内存模型是共享内存的并发模型,线程之间主要通过读-写共享变量来完成隐式通信。
三、JVM中的共享变量和线程独占变量
共享变量
在Java中所有实例域,静态域和数组元素都是放在堆内存中(所有线程均可以访问到,是可以共享的)。
线程独占
局部变量,方法定义参数和异常处理器参数不会在线程间共享
共享数据会出现线程安全的问题,而非共享数据不会出现线程安全的问题
四、描述一下JMM的抽象结构模型
我们知道CPU的处理速度和主存的读写速度不是一个量级的,为了平衡这种巨大的差距,每个CPU都会有缓存。因此,共享变量会先放在主存中,每个线程都有属于自己的工作内存,并且会把位于主存中的共享变量拷贝到自己的工作内存中,之后读写操作均使用位于工作内存的变量副本,并且在某个时刻将工作内存的变量副本写到主存中去。JMM就从抽象层定义了这种方式,并且JMM决定了一个线程对共享变量的写入何时对其他线程是可见的。
如图为JMM抽象示意图,线程A和线程B 之间要完成通信的话,要经理如下两步:线程A从主内存中将共享变量读入线程A 的工作内存后并进行操作,之后将数据重新写会主内存中;线程B从主内存中读取最新的共享变量。
从横向去看,线程A和线程B好像通过共享变量在进行隐式通信。这其中就有个问题,如果线程A更新后数据并没有及时的写回,而此时线程B读到了过期的数据,这就出现了脏读现象,可以通过同步机制(控制不同线程操作发生的相对顺序)来解决或者通过valatitl关键字是的每次volatitl变量都能够强制刷新到主存,从而对每个线程都是可见的
五、由于JMM,多线程情况下可能出现哪些问题
从上面内存抽象结构来说,可能出现数据脏读的现象,这就是数据可见性的问题。另外,重排序在多线程中不注意的话也容易存在一些问题,比如一个经典的问题DCL(双重检验锁),这就是需要禁止重排序。另外,在多线程下原子操作例如:i++不加注意也容易出现线程安全的问题。
单总的来说,在多线程开发时需要从原子性、有序性、可见性三个方面进行考虑。
J.U.C包下的并发工具类和并发容器也是需要花时间去掌握的。