Files
examination/topics/interview-prep/go-java-concurrency/true_false.json
T
wonder 0f68a64829
Deploy Examination / deploy (push) Successful in 10s
feat: add interview-prep topic group with 250 questions (6 subtopics, 5 question types)
Subtopics:
- distributed-microservice: 45 questions (分布式微服务架构)
- message-queue: 45 questions (消息队列)
- k8s-observability: 45 questions (K8s与可观测性)
- go-java-concurrency: 45 questions (Go/Java并发模型)
- database-advanced: 35 questions (数据库进阶)
- ai-engineering: 35 questions (AI工程实践)

Question types: single_choice, true_false, fill_blank, short_answer, code_reading
2026-09-09 16:36:27 +08:00

152 lines
10 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"topic": "go-java-concurrency",
"type": "true_false",
"schema_version": "1.0.0",
"generated": "2026-09-09T16:21:56+08:00",
"questions": [
{
"id": "tf-001",
"type": "true_false",
"difficulty": 2,
"tags": [
"go",
"channel"
],
"question": "在Go中,向已关闭的channel发送数据会导致panic,但从已关闭的channel接收数据会立即返回零值且ok为false。",
"answer": true,
"explanation": "Go中channel的close语义明确规定:向已关闭的channel发送数据会触发panic(send on closed channel),而从已关闭的channel接收数据不会阻塞,而是返回该元素类型的零值,第二个返回值ok为false。这是channel安全关闭的核心规则——关闭者负责发送端的停止,接收者只需检查ok值。",
"source": null,
"related": []
},
{
"id": "tf-002",
"type": "true_false",
"difficulty": 3,
"tags": [
"go",
"goroutine",
"pprof"
],
"question": "Go中goroutine泄漏最常见的原因之一是向无缓冲channel发送数据后,没有对应的接收者,导致发送方goroutine永远阻塞。",
"answer": true,
"explanation": "goroutine泄漏的本质是goroutine无法正常退出。向无缓冲channel发送时,如果没有goroutine在接收,发送方会永久阻塞。类似地,从无人发送的channel接收也会阻塞。其他常见泄漏场景包括:context未正确取消导致的无限等待循环、select中没有default分支且所有case都不就绪等。可以通过pprof的goroutine profile(runtime.NumGoroutine()或net/http/pprof)来定位泄漏的goroutine及其阻塞堆栈。",
"source": null,
"related": []
},
{
"id": "tf-003",
"type": "true_false",
"difficulty": 3,
"tags": [
"go",
"gmp"
],
"question": "Go的GMP调度模型中,当一个M(系统线程)发现本地P的本地队列为空时,会先尝试从全局队列获取G,再尝试从其他P的本地队列偷取(work-stealing)一半的G。",
"answer": true,
"explanation": "GMP调度模型中,M绑定P后优先从P的本地队列获取G执行。当本地队列为空时,调度器的窃取逻辑为:1)先检查全局队列(global run queue);2)再尝试netpoller(网络轮询器);3)最后从其他P的本地队列偷取(随机选择一个P,偷取其本地队列一半的G)。sysmon监控线程会定期检测长时间运行的G(抢占式调度),并将空闲P绑定到空闲M。",
"source": null,
"related": []
},
{
"id": "tf-004",
"type": "true_false",
"difficulty": 4,
"tags": [
"java",
"jmm",
"volatile"
],
"question": "在Java内存模型(JMM)中,volatile变量的写操作对后续所有线程的读操作都可见,因此volatile可以完全替代synchronized来保证复合操作的原子性。",
"answer": false,
"explanation": "volatile确实保证了可见性(写入后立即刷新到主内存,读取时从主内存加载)和有序性(禁止指令重排序),但它不保证复合操作的原子性。例如volatile int count; count++实质是读-改-写三步操作,多个线程并发执行时仍会出现竞态条件。对于复合操作的原子性,需要使用synchronized、ReentrantLock或java.util.concurrent.atomic包中的原子类(如AtomicInteger的CAS操作)。volatile的经典适用场景是状态标志位(boolean flag)和双重检查锁定(DCL)单例模式。",
"source": null,
"related": []
},
{
"id": "tf-005",
"type": "true_false",
"difficulty": 3,
"tags": [
"java",
"aqs",
"synchronized"
],
"question": "Java中AQS(AbstractQueuedSynchronizer)是ReentrantLock和Semaphore等同步器的核心实现基础,它通过CLH队列变体和volatile状态变量来实现线程排队与唤醒。",
"answer": true,
"explanation": "AQS是java.util.concurrent包的基石,其核心机制为:1)内部维护一个volatile int state变量表示同步状态;2)使用CLH(Craig, Landin, and Hagersten)队列变体实现线程排队,每个等待线程被封装为Node节点;3)获取锁失败的线程被包装为Node加入CLH队列尾部,然后通过LockSupport.park()阻塞;4)释放锁时通过unparkSuccessor()唤醒队列中的下一个线程。ReentrantLock通过state表示重入次数,Semaphore通过state表示可用许可数,CountDownLatch通过state表示倒计数值。而synchronized从JVM层面实现,不依赖AQS。",
"source": null,
"related": []
},
{
"id": "tf-006",
"type": "true_false",
"difficulty": 2,
"tags": [
"go",
"sync"
],
"question": "Go的sync.Once保证传入的函数只被执行一次,即使多个goroutine同时调用Do方法,也只有一个goroutine会执行该函数,其余goroutine会阻塞等待其完成。",
"answer": true,
"explanation": "sync.Once内部通过atomic.LoadInt32/StoreInt32检查并设置标志位来保证函数只执行一次。其Do方法的实现逻辑为:先通过原子操作检查done标志,若已执行则直接返回;若未执行,则通过Mutex加锁后再次检查(double-check)并执行函数。其他并发调用Do的goroutine会在Mutex上阻塞,直到执行的goroutine完成函数调用并释放锁。这保证了初始化代码的线程安全执行,是Go中实现懒初始化单例的标准方式。",
"source": null,
"related": []
},
{
"id": "tf-007",
"type": "true_false",
"difficulty": 4,
"tags": [
"java",
"forkjoinpool"
],
"question": "Java的ForkJoinPool采用工作窃取(work-stealing)算法,空闲的工作线程会从其他繁忙线程的任务队列尾部偷取任务执行,commonPool使用ForkJoinPool.defaultParallelism()作为默认并行度。",
"answer": true,
"explanation": "ForkJoinPool的核心设计是工作窃取:每个工作线程维护一个双端队列(deque),新任务从队列头部推入(push),本线程也从头部取出执行(LIFO,有利于局部性)。当某个线程的队列为空时,它会随机选择其他线程的队列,从其尾部窃取任务(FIFO,减少竞争)。commonPool是静态共享池,通过ForkJoinPool.commonPool()获取,默认并行度Runtime.getRuntime().availableProcessors()-1(当大于1时),适用于ParallelStream和CompletableFuture等场景。RecursiveTask(有返回值)和RecursiveAction(无返回值)是ForkJoinTask的两个子类,用于定义可分解的递归任务。",
"source": null,
"related": []
},
{
"id": "tf-008",
"type": "true_false",
"difficulty": 4,
"tags": [
"jmm",
"happens-before",
"go"
],
"question": "Go的内存模型中,goroutine的创建(go关键字)发生在该goroutine的执行之前,而channel的每次发送操作都happens-before对应的接收操作完成。",
"answer": false,
"explanation": "Go内存模型的happens-before规则中:1)goroutine的创建确实happens-before该goroutine的执行开始——这是正确的。2)但对于无缓冲channel:发送操作happens-before对应的接收操作完成;而对于有缓冲channel:第k次发送happens-before第k次接收的完成。关键区别在于'完成'——接收操作的完成是指接收到了数据,而不是仅仅开始接收。该题将两种channel混为一谈,表述不够准确,且channel的发送happens-before的是'对应的接收完成'而非'接收操作本身',存在语义偏差,因此判定为false。",
"source": null,
"related": []
},
{
"id": "tf-009",
"type": "true_false",
"difficulty": 3,
"tags": [
"java",
"thread"
],
"question": "Java中通过ThreadPoolExecutor创建线程池时,核心参数maximumPoolSize必须大于等于corePoolSize,当核心线程数未满时新任务会创建核心线程执行,核心线程满后任务会先进入工作队列,队列满后才创建非核心线程。",
"answer": true,
"explanation": "ThreadPoolExecutor的任务提交流程严格遵循以下顺序:1)当前线程数 < corePoolSize → 创建新核心线程执行任务;2)核心线程满 → 将任务放入workQueue(工作队列)等待;3)队列已满且线程数 < maximumPoolSize → 创建非核心线程执行任务;4)线程数已达maximumPoolSize且队列满 → 执行拒绝策略(AbortPolicy/CallerRunsPolicy/DiscardPolicy/DiscardOldestPolicy)。maximumPoolSize < corePoolSize在语义上不成立,构造时虽然不会抛异常,但实际线程数永远不会超过corePoolSize。注意:如果使用无界队列(如LinkedBlockingQueue),maximumPoolSize实际上不会生效。",
"source": null,
"related": []
},
{
"id": "tf-010",
"type": "true_false",
"difficulty": 2,
"tags": [
"java",
"jfr"
],
"question": "Java Flight Recorder(JFR)是JDK内置的低开销性能分析工具,通过事件采样的方式记录CPU、内存、I/O、线程等运行时信息,可通过jcmd或jfr命令行工具启动录制,也可在代码中通过Recording API编程控制。",
"answer": true,
"explanation": "JFR是Oracle JDK和OpenJDK(JEP 171/328/336)内置的生产级监控框架,设计目标是开销低于1%。其核心特点包括:1)基于事件驱动的采样机制,预定义了数百种事件类型(如jdk.CPULoad、jdk.GarbageCollection、jdk.ThreadStart等);2)支持命令行启动(jcmd <pid> JFR.start、jfr start/stop/dump)和编程方式(new Recording().start());3)录制数据以.jfr文件存储,可通过JDK Mission Control(JMC)可视化分析,生成火焰图等;4)从JDK 11起可免费用于生产环境(此前商业特性)。JFR与异步采样profiling配合,能有效定位CPU热点、锁竞争、GC停顿等问题。",
"source": null,
"related": []
}
]
}