Redis 可用于实现分布式锁,文中系统梳理了七种方案:① SETNX + EXPIRE(非原子)② SETNX + 时间戳值(依赖客户端时钟)③ Lua 脚本实现原子 SETNX+EXPIRE④ SET EX PX NX(仍有误删、超时问题)⑤ 在值中加入唯一标识并用 Lua 检查后删除⑥ Redisson 框架的看门狗机制自动续期⑦ Redlock 多节点算法通过多数节点获取锁并在多个 Master 上安全释放。文章还强调分布式锁应具备互斥、超时释放、可重入、高性能/可用和安全性等特征。

本次面试主要围绕多线程展开。面试者首先阐述了使用多线程提高资源利用率和并发能力的原因,并举例说明了Tomcat处理请求、高并发数据处理、异步任务和定时任务等应用场景。随后,讨论了线程安全问题,面试者解释了线程安全的概念,并分享了处理线程安全问题的常用方法,包括原子类、线程工具类(CountDownLatch、Semaphore)、并发集合、synchronized关键字和分布式锁。 面试深入探讨了synchronized的底层原理,即通过monitorenter和monitorexit指令以及对象头中的monitor实现锁机制。同时,对比了synchronized和ReentrantLock的区别,包括锁的释放方式、公平性、可中断性、超时获取锁和非阻塞获取锁等特性。最后,面试者解释了公平锁与非公平锁的概念,以及CAS(Compare And Swap)乐观锁的原理和应用,例如AtomicInteger的getAndIncrement()方法。面试官认为面试者基础掌握扎实。

小邹参加Redis面试,面试官围绕Redis的线程模型、性能、持久化和高可用等核心概念进行了提问。面试中,小邹展现了对Redis版本差异、单线程优势(避免锁竞争、高效数据结构、I/O多路复用)的理解,并阐述了AOF和RDB持久化方式的原理及优缺点。他也解释了Redis选择后写日志的原因,以及RDB快照的阻塞问题和解决方法。 关于高可用,小邹介绍了主从复制、哨兵模式和Redis集群三种方案,并区分了哨兵模式与集群模式的区别:哨兵模式主要提升可用性,而集群模式则能扩展写能力和存储容量。 面试过程中,小邹在Redis集群的节点选择机制上表现出知识盲点,最终面试官补充说明了Redis Cluster采用类一致性哈希算法,将数据分散到16384个槽位上,实现节点选择。面试整体考察了小邹对Redis底层原理的掌握程度。

这段代码演示了Java中字符串比较的特性。`String s1 = new String("xiaozou")` 创建了一个堆上的String对象和一个字符串常量池中的“xiaozou”常量。`String s2 = "xiaozou"` 直接从字符串常量池获取“xiaozou”的引用。因此,`s1 == s2` 返回false,因为它们指向不同的内存地址。 `String s3 = s1.intern()` 将 `s1` 对应的字符串“xiaozou”添加到字符串常量池(如果不存在),并返回常量池中该字符串的引用。由于 `s2` 也指向字符串常量池中的“xiaozou”,所以 `s2 == s3` 返回true。总结来说,此代码强调了`==`比较的是引用地址,而`intern()`方法的作用是将字符串添加到常量池并返回其引用,从而影响字符串比较的结果。

该文章探讨了一种通过反射机制修改String对象内容的方法,旨在使String变量`s`的输出从"abc"变为"abcd",同时保持其引用不变。文章首先排除了使用`StringBuilder`的`append()`和`String`的`replace()`方法,因为它们无法满足需求。随后,文章展示了利用反射修改String类中的`value`属性的正确实现方式。 然而,文章指出在JDK11及更高版本中,这种做法会抛出`IllegalArgumentException`异常,因为String的`value`字段被声明为final,JVM在编译时进行了优化,将其视为常量,不允许直接修改。文章解释了异常产生的原因,并强调了在更高版本的JDK中,反射修改final字段可能会被禁止。