面试题之并发相关专栏五

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

当一个变量被volatile修饰后,具备两个特性:

  • 保证此变量对所有线程的可见性,当一条线程修改了这个变量的值,新值对于其他线程是可以立即得知的,而普通变量做不到这一点。
  • 禁止指令重排序优化,普通变量仅仅能保证在方法执行过程中,得到正确结果,但是不保证程序代码的执行顺序。

内存模型定义了8种内存间操作来保证可见性:

  •     lock/unlock
  •     read/write
  •     load/store
  •     use/assgin

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

这很显然并不是的。基于volatile变量的运算在并发下不一定是线程安全的,volatile变量 在各个线程的工作内存,不存在一致性问题(各个线程的工作内存中volatile变量,每次使用前都要刷新到主内存),但是java里面的运算并不是原子操作,导致volatile变量的运算在并发下也不一定就是线程安全的。volatile只保证了可见性,并不能保证原子性。

三、请对比下volatile和Synchronized的异同?

  • Synchronized既保证了可见性,又保证了原子性,而volatile只能保证可见性,不能保证原子性;
  • volatile仅能使用在变量级别;Synchronized则可以使用在变量、方法、和类级别的;
  • volatile本质是在告诉JVM当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;Synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住;
  • volatile不会造成线程的阻塞;Synchronized可能会造成线程的阻塞;
  • volatile标记的变量不会被编译器优化;Synchronized标记的变量可以被编译器优化;

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

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

五、谈谈你对ThreadLocal的理解,使用ThreadLocal需要注意些什么?

  • ThreadLocal 变量解决了多线程环境下单个线程中变量的共享问题,使用名为ThreadLocalMap的哈希表进行维护(key为ThreadLocal变量名,value为ThreadLocal变量的值);
  • 设想如果将一个大对象放入ThreadLocal 中,并且还没有remove。那么就可能会造成OutOfMemoryError,如果不会造成OutOfMemoryError那么也会浪费Java堆内存。使用时需要注意以下几点:
  1.     线程之间的threadLocal变量是互不影响的;
  2.     使用private final static进行修饰,防止多实例时内存的泄露问题;
  3.     线程池环境下使用后将threadLocal变量remove掉或设置成一个初始值;
发布了250 篇原创文章 · 获赞 112 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/Weixiaohuai/article/details/105332294