【高并发】关于线程池,蚂蚁金服面试官问了我这些内容!! (2)

submit()、ExecutorService.submit()方法返回的是Future对象。可以用isDone()来查询Future是否已经完成,当任务完成时,它具有一个结果,可以调用get()来获取结果。也可以不用isDone()进行检查就直接调用get(),在这种情况下,get()将阻塞,直至结果准备就绪。Java内存模型相关问题

什么是Java的内存模型,Java中各个线程是怎么彼此看到对方的变量的?

Java的内存模型定义了程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出这样的底层细节。此处的变量包括实例字段、静态字段和构成数组对象的元素,但是不包括局部变量和方法参数,因为这些是线程私有的,不会被共享,所以不存在竞争问题。

Java中各个线程是怎么彼此看到对方的变量的呢?
Java中定义了主内存与工作内存的概念、所有的变量都存储在主内存,每条线程还有自己的工作内存,保存了被该线程使用到的变量的主内存副本拷贝。

线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,不能直接读写主内存的变量。不同的线程之间也无法直接访问对方工作内存的变量,线程间变量值的传递需要通过主内存。

请谈谈volatile有什么特点,为什么它能保证变量对所有线程的可见性?

关键字volatile是Java虚拟机提供的最轻量级的同步机制。当一个变量被定义成volatile之后,具备两种特性、

(1)保证此变量对所有线程的可见性。当一条线程修改了这个变量的值,新值对于其他线程是可以立即得知的。而普通变量做不到这一点。
(2)禁止指令重排序优化。普通变量仅仅能保证在该方法执行过程中,得到正确结果,但是不保证程序代码的执行顺序。Java的内存模型定义了8种内存间操作、lock和unlock把一个变量标识为一条线程独占的状态。把一个处于锁定状态的变量释放出来,释放之后的变量才能被其他线程锁定。read和write把一个变量值从主内存传输到线程的工作内存,以便load。把store操作从工作内存得到的变量的值,放入主内存的变量中。

load和store把read操作从主内存得到的变量值放入工作内存的变量副本中。把工作内存的变量值传送到主内存,以便write。use和assgin把工作内存变量值传递给执行引擎。将执行引擎值传递给工作内存变量值。volatile的实现基于这8种内存间操作,保证了一个线程对某个volatile变量的修改,一定会被另一个线程看见,即保证了可见性。

既然volatile能够保证线程间的变量可见性,是不是就意味着基于volatile变量的运算就是并发安全的?

显然不是的。基于volatile变量的运算在并发下不一定是安全的。volatile变量在各个线程的工作内存,不存在一致性问题(各个线程的工作内存中volatile变量,每次使用前都要刷新到主内存)。但是Java里面的运算并非原子操作,导致volatile变量的运算在并发下一样是不安全的。

请对比下volatile对比Synchronized的异同。

Synchronized既能保证可见性,又能保证原子性,而volatile只能保证可见性,无法保证原子性。

ThreadLocal和Synchonized都用于解决多线程并发访问,防止任务在共享资源上产生冲突。但是ThreadLocal与Synchronized有本质的区别。

Synchronized用于实现同步机制,是利用锁的机制使变量或代码块在某一时该只能被一个线程访问,是一种“以时间换空间”的方式。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,根除了对变量的共享,是一种“以空间换时间”的方式。

请谈谈ThreadLocal是怎么解决并发安全的?

ThreadLocal这是Java提供的一种保存线程私有信息的机制,因为其在整个线程生命周期内有效,所以可以方便地在一个线程关联的不同业务模块之间传递信息,比如事务ID、Cookie等上下文相关信息。ThreadLocal为每一个线程维护变量的副本,把共享数据的可见范围限制在同一个线程之内,其实现原理是,在ThreadLocal中有一个Map,用于存储每一个线程的变量的副本。

很多人都说要慎用ThreadLocal,谈谈你的理解,使用ThreadLocal需要注意些什么?

使用ThreadLocal要注意remove!ThreadLocal的实现是基于一个所谓的ThreadLocalMap,在ThreadLocalMap中,它的key是一个弱引用。通常弱引用都会和引用队列配合清理机制使用,但是ThreadLocal是个例外,它并没有这么做。这意味着,废弃项目的回收依赖于显式地触发,否则就要等待线程结束,进而回收相应ThreadLocalMap!这就是很多OOM的来源,所以通常都会建议,应用一定要自己负责remove,并且不要和线程池配

重磅福利

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

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