Java进阶与面试——多线程、CAS、volatile详解、DCL单例

1. 启动线程的3种方式

  • 继承Thread
  • 实现Runable接口
  • 启动一个线程池
    严格的说,第三种其实只是线程池内部通过前两种方式开启了一个线程

2. 主线程中new 3个子线程,如何保证t1、t2、t3按顺序执行

new t1();
new t2() { t1.join... }//t2等t1结束后继续
new t3() { t2.join... }//t3等t2结束后继续
t1.start()
t2.start()
t3.start()
t3.join() //主线程等待t3执行完毕再继续

3. 锁升级的概念

JDK1.5之前java中的synchronized锁是重量级锁,是向操作系统申请锁,程序执行会从用户态切换到内核态(通过系统调用中断),锁的申请过程开销比较大。
JDK1.5开始锁做了优化,如果只有一个线程执行synchronized代码(临界区),操作系统只是在被锁住的对象的对象头部64个bit的markword进行标记,记录线程ID,这种偏向于第一个线程的“锁”叫做偏向锁(实际上是没加锁);当有第二个线程开始争夺执行机会的时候,会升级到自旋锁。即通过CPU的CAS指令进行控制,CAS失败的线程会“空转”直到10次失败或者获得锁,10次后还未等到则升级为内核态拿“重量级锁”。所以经过Oracle Hotspot JVM实现上的优化,synchronized的效率大部分时候并不比使用AtomicXXX来得低。

4. 什么时候适合用自旋锁CAS

临界区的代码本身执行时间比较短,线程数量不会太多的时候适合CAS
自旋锁本质是一种“乐观锁”,它假定在绝大多数情况下,对资源的竞争不会很激烈,这是基于工程实践中的一种优化。
相反,需要长时间执行,或者线程数量可能比较多的时候用“重量级锁”,防止很多线程“忙占”CPU(busy wait)。

5. 自旋锁的底层实现,ABA问题

  1. AtomicReference/AtomicInteger/AtomicLong。底层通过checkAndSwap和操作系统底层硬件的支持保证“检查和设置”是一个原子操作。
  2. ABA问题对于很多无状态的变量,在语义和结果上并没有什么大问题。如果从实现语义上需要避免ABA问题,使用AtomicStampedReference。

6. volatile关键字的作用

  1. 保证多线程的可见性。一个线程对volatile变量的修改,另一个线程能够及时看到改变后的值(线程私有变量跟主内存变量同步更新)。通过底层CPU缓存一致性协议来保证。volatile会告诉编译器,不要把此类变量优化到寄存器中,每次都要老老实实的从内存中读取,因为它们随时都可能变化。
  2. 通过添加内存屏障,禁止指令重排序。现代操作系统能够并行执行指令,用以提高执行效率。java编译器也可能对编译后的指令进行重新排序。

附:DCL单例

一个标准的双重检查单例(DCL, Double Check Lock)实现上,单例对象应该是volatile的,否则超高并发极端情况下,可能出现getInstance()拿到的对象刚从内存中分配出一块内存,但还未调用构造函数进行初始化,对象指针就已经不是null而暴露出来了。这种情况下,这个线程拿到的是一个还是初始化的对象。如果调用未正确初始化对象的方法,将导致程序崩溃。

public class TestSingleton {
    private static volatile TestSingleton instance;
    // 私有化构造函数
    private TestSingleton() { }
    public static TestSingleton getInstance() {
        // 进入临界区之前,第一重检查
        if (instance == null) {
            synchronized (TestSingleton.class) {
            	// 进入临界区后,进行第二重检查
                if (instance == null) {
                    instance = new TestSingleton();
                }
            }
        }
        return instance;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值