多线程——面试中一个常考的内容(7)

张开发
2026/4/8 1:18:43 15 分钟阅读

分享文章

多线程——面试中一个常考的内容(7)
上次讲到了wait与notify那么现在我们继续往下讲。单例模式这是一种设计模式设计模式也就相当于象棋的棋谱大佬们把一些典型的问题场景整理出来并且针对这些场景代码该怎么写具体方案给出了一些指导和建议。而单例模式就是设计模式中一种非常典型的模式也是比较简单的模式还是校招中最容易被考到的设计模式。它强制要求某个类在某个程序中只有唯一一个实例不允许创建多个实例也就是不允许new多次。单例模式强制要求一个类不能创建多个对象这个不是口头上的协定而是要通过机器或程序强制要求的。通过一些编程技巧达成上述的“强制要求”在代码中如果创建了多个实例就会直接编译失败。下面是我们实现单例方式的方式1.饿汉方式饿汉即迫切也就是很快初始化对象静态成员的初始化是在类加载的阶段触发的而类加载往往就是在程序一启动就会触发。后续统一通过getInstance这个方法来获取这里的实例。这个私有的方法是单例方式的点睛之笔在类外进行new操作就会编译失败。当然在初始化对象时可以根据需要往括号里传参。下图是饿汉方式的代码2.懒汉方式饿和懒是相对的饿是尽早创建实例而懒是尽量晚的创建实例甚至可能不创建了。当然“懒”在计算机中是褒义词懒的另一个含义是——高效率。为什么这么说假设有一个很大的文件如千万字的小说你把编辑器打开的时候是想把所有的内容都从文件加载到内存中再显示还是只把一部分内容加载并显示呢很明显选择后者因为前者明显卡顿就算加载了这么多你也看不过来的而后者中后续如果用户翻页随着翻页随时加载后续数据就可以节省很大的空间。懒汉模式之下创建实例的时机是在第一次使用的时候而不是在程序启动的时候。可是咱们当前讲的这个章节叫多线程这些与多线程有什么关系上述这些内容都是铺垫接下来才是正题。线程安全问题刚才编写的两份代码饿汉、懒汉是否是线程安全的如果不是该怎么办非常经典的面试题对比一下这两个代码这里可以发现饿汉是不会出现线程安全问题的而真正有问题的是懒汉模式。那么我们在多线程的情况下t1、t2线程拆开getInstance之后分析可以看到对象instance为null那么两个线程都会new一个新的对象相当于创建了两次对象即使线程调度的随机性出现的覆盖现象会使结果不变与预期结果相同可是new的这个对象new的过程中可能要把100G的数据从硬盘加载到内存两个就是200G也就是说本来启动时间大约是10分钟由于上述的bug加载两份导致最终时间远远超过了20分钟。那么我们改怎么办观察getInstance方法if循环里套着新的对象的初始化虽然“”是原子的但是有if条件也就是“条件修改”就不是原子的了于是我们希望条件和修改能够打包成原子于是我们就想到了加锁。1.加锁变原子的当然两个线程都加锁两个线程加锁的对象相同于是我们再拆开getInstance分析当我们加锁后上面先执行的是抢到锁并成功加锁的线程另一个线程就要阻塞等待线程t1执行了if初始化了对象之后释放锁然后t2加锁此时instance对象已经被初始化了就不是null了因此直接返回就可以了不用new了也就少new了一次。可是这样还有没有别的问题之前提到只要加了锁就会影响执行效率。当我们把实例创建好了之后初始化好了后续再调用getInstance此时都是直接执行return操作如果只是进行ifreturn这就是纯粹的读取操作了该操作就不涉及线程安全问题但是每次调用上述方法之后都会触发一次加锁虽然不涉及线程安全问题了但多线程情况下这里的加锁就会相互阻塞影响线程的执行效率。2.锁外加if条件判断来确定是否加锁——提高执行效率最外层的if是为了判定是否需要加锁最里层的if是为了判断是否需要new对象这就是按需加锁真正涉及到线程安全时再加锁不涉及时就不加锁。如果实例已经创建过了就不涉及线程安全问题反之就涉及线程安全问题。仔细分析一下还有什么问题3.指令重排序问题与volatile可是volatile解决的问题更主要的是指令重排序问题。这个也是编译器优化的一种体现形式编译会在逻辑不变的前提下调整你代码的执行顺序以达到提升性能的效果。我们看创建实例这句代码这个代码涉及三个步骤1.申请内存空间绝对是第一步2.在空间上构造对象初始化3.内存空间的首地址复制给引用变量正常来说这三个步骤是按照123的顺序执行的但是在指令重排序下可能成为132这样的排序单线程环境下123还是132是无所谓的但在多线程中可能会出现bug。32之间如果再用getInstance创建的s对象、用s来调用方法时这个对象可能是未初始化的而初始化操作恰好在下一步。于是我们给对象instance加volatile今天的内容就到这里明天我们继续。我的gitee链接https://gitee.com/QQ2240635095/java4_6.git

更多文章