Skip to content

Commit db32ff6

Browse files
author
REALROOK1E
committed
修正并发编程文档中的性能数据和引用来源
之前文档里有些性能对比用了很具体的数字(比如10倍、10-20倍),但没有给出测试环境和数据来源,容易误导读者。这次把这些改成了相对描述,像" 显著优于\、\性能更好\这样。 另外threadlocal那篇提到的美团事故案例也找不到出处,就改成了通用的场景说明。 最后给jmm.md、cas.md、threadlocal.md都加上了参考资料章节,标注了官方文档、技术书籍和论文的出处,方便大家深入学习。
1 parent 50a41eb commit db32ff6

File tree

4 files changed

+56
-14
lines changed

4 files changed

+56
-14
lines changed

docs/java/concurrent/aqs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ notFull.signal(); // 通知生产者可以生产
323323
根据 Doug Lea(AQS 作者)的测试和实际生产环境的统计:
324324

325325
**吞吐量对比**
326-
- 在高并发场景下,非公平锁的吞吐量通常是公平锁的 **10-20 倍**
326+
- 在高并发场景下,非公平锁的吞吐量通常显著高于公平锁(可达数倍甚至十倍以上的差距)
327327
- 原因:减少了线程切换的开销。公平锁每次都要排队,涉及线程的阻塞和唤醒;非公平锁允许"插队",如果锁刚好可用,当前线程可以立即获得,避免了上下文切换
328328

329329
**响应时间对比**

docs/java/concurrent/cas.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ public long sum() {
225225
}
226226
```
227227

228-
这种设计与 `ConcurrentHashMap``counterCells` 机制完全一致,都是通过**分散热点、化整为零**的思想实现高并发下的性能优化。在累加场景下,`LongAdder` 的性能可比 `AtomicLong` 高出数倍
228+
这种设计与 `ConcurrentHashMap``counterCells` 机制完全一致,都是通过**分散热点、化整为零**的思想实现高并发下的性能优化。在高并发累加场景下,`LongAdder` 的性能优于 `AtomicLong`
229229

230230
### 循环时间长开销大
231231

@@ -247,3 +247,12 @@ CAS 操作仅能对单个共享变量有效。当需要操作多个共享变量
247247
在 Java 中,CAS 通过 `Unsafe` 类中的 `native` 方法实现,这些方法调用底层的硬件指令来完成原子操作。由于其实现依赖于 C++ 内联汇编和 JNI 调用,因此 CAS 的具体实现与操作系统以及 CPU 密切相关。
248248

249249
CAS 虽然具有高效的无锁特性,但也需要注意 ABA 、循环时间长开销大等问题。
250+
251+
## 参考资料
252+
253+
- 《Java 并发编程的艺术》方腾飞等著, 第 2 章 Java 并发机制的底层实现原理
254+
- 《深入理解 Java 虚拟机(第 3 版)》周志明著, 第 13 章 线程安全与锁优化
255+
- OpenJDK Unsafe 源码: <https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/jdk/internal/misc/Unsafe.java>
256+
- Intel® 64 and IA-32 Architectures Software Developer's Manual, Volume 3A: System Programming Guide, Part 1, Chapter 8: Multiple-Processor Management
257+
- Doug Lea - A Java Fork/Join Framework: <http://gee.cs.oswego.edu/dl/papers/fj.pdf>
258+
- Oracle Docs - java.util.concurrent.atomic Package Summary: <https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html>

docs/java/concurrent/jmm.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ class VolatileExample {
295295

296296
1. **无锁机制**: volatile 不需要加锁,不会阻塞线程,而 synchronized 会导致线程上下文切换
297297
2. **轻量级同步**: volatile 只保证单个变量的可见性,synchronized 保证整个代码块的原子性
298-
3. **性能差异**: 在高竞争场景下,volatile 读写操作比 synchronized 快约 10 倍以上
298+
3. **性能差异**: 在高竞争场景下,volatile 读写操作比 synchronized 快得多,因为避免了线程阻塞和上下文切换的开销
299299

300300
**适用场景对比:**
301301

@@ -350,4 +350,13 @@ public class Singleton {
350350
- 嘿,同学,你要的 Java 内存模型 (JMM) 来了:<https://xie.infoq.cn/article/739920a92d0d27e2053174ef2>
351351
- JSR 133 (Java Memory Model) FAQ:<https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html>
352352

353+
## 参考资料
354+
355+
- 《深入理解 Java 虚拟机(第 3 版)》周志明著, 第 12 章 Java 内存模型与线程
356+
- 《Java 并发编程实战》Brian Goetz 著, 第 16 章 Java 内存模型
357+
- JSR-133: Java Memory Model and Thread Specification: <https://jcp.org/en/jsr/detail?id=133>
358+
- The JSR-133 Cookbook for Compiler Writers: <http://gee.cs.oswego.edu/dl/jmm/cookbook.html>
359+
- Java Memory Model Examples: <http://www.cs.umd.edu/~pugh/java/memoryModel/>
360+
- Doug Lea's Workstation - JSR-133 (Java Memory Model) FAQ: <https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html>
361+
353362
<!-- @include: @article-footer.snippet.md -->

docs/java/concurrent/threadlocal.md

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -307,20 +307,23 @@ public void processRequest(Request request) {
307307
}
308308
```
309309

310-
**美团技术团队的实践经验**
310+
**大厂实践经验总结**
311311

312-
在美团的实际项目中,曾经出现过因为 ThreadLocal 未清理导致的严重生产事故:
313-
1. 在线程池中使用 ThreadLocal 存储用户权限信息
314-
2. 某次请求处理完后,由于异常导致未执行 remove()
315-
3. 该线程被分配给下一个请求时,错误地使用了上一个用户的权限信息
316-
4. 导致越权访问,产生了严重的安全漏洞
312+
在实际生产环境中,线程池与 ThreadLocal 使用不当可能导致严重问题:
317313

318-
修复方案:
319-
1. 强制要求所有 ThreadLocal 使用都必须配合 try-finally + remove()
320-
2. 通过静态代码扫描工具检测未正确清理的 ThreadLocal 使用
321-
3. 在线程池提交任务时增加清理 ThreadLocal 的包装器
314+
**常见问题场景**
315+
1. 线程池中使用 ThreadLocal 存储用户上下文信息(如用户ID、权限等)
316+
2. 任务执行完成后,未在 finally 块中调用 remove()
317+
3. 线程被复用时,下一个任务读取到上一个任务的残留数据
318+
4. 可能导致数据混乱、业务逻辑错误、甚至安全漏洞(如权限信息错乱)
322319

323-
这个案例充分说明了在线程池场景下正确使用 ThreadLocal 的重要性。记住:**ThreadLocal 用完一定要 remove(),特别是在线程池环境下!**
320+
**推荐的修复方案**(参考阿里巴巴规范):
321+
1. **强制使用 try-finally**:所有 ThreadLocal 操作都必须在 finally 中调用 remove()
322+
2. **代码审查工具**:通过静态分析工具(如阿里的 p3c)检测未正确清理的 ThreadLocal
323+
3. **线程池包装器**:在任务提交和执行前后自动清理 ThreadLocal
324+
4. **监控告警**:监控线程池内存使用情况,及时发现内存泄漏
325+
326+
这些最佳实践充分说明:**ThreadLocal 用完一定要 remove(),特别是在线程池环境下!**
324327

325328
### `ThreadLocal.set()`方法源码详解
326329

@@ -1061,4 +1064,25 @@ public class MyThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
10611064

10621065
MQ 发送的消息体中自定义属性`requestId`,接收方消费消息后,自己解析`requestId`使用即可。
10631066

1067+
## 参考资料
1068+
1069+
### 官方文档与规范
1070+
1. [OpenJDK ThreadLocal 源码](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/lang/ThreadLocal.java) - JDK 8 官方实现
1071+
2. [Java Language Specification](https://docs.oracle.com/javase/specs/) - Java 语言规范
1072+
1073+
### 开源规范
1074+
1. [阿里巴巴 Java 开发手册](https://github.com/alibaba/p3c) - GitHub 开源版本
1075+
- 第一章"编程规约" → (七)并发处理
1076+
- 强制规范:"必须回收自定义的 ThreadLocal 变量,尤其在线程池场景下..."
1077+
1078+
### 技术书籍
1079+
1. 《深入理解 Java 虚拟机(第3版)》- 周志明,机械工业出版社
1080+
-2"自动内存管理" - 引用类型详解
1081+
2.Java 并发编程实战》(Java Concurrency in Practice) - Brian Goetz
1082+
-3"对象的共享" - ThreadLocal 的使用与陷阱
1083+
1084+
### 在线资源
1085+
1. [Why is ThreadLocal's key a weak reference?](https://stackoverflow.com/questions/10739289) - StackOverflow 深度讨论
1086+
2. [Understanding Weak References](https://docs.oracle.com/javase/8/docs/api/java/lang/ref/WeakReference.html) - Oracle 官方文档
1087+
10641088
<!-- @include: @article-footer.snippet.md -->

0 commit comments

Comments
 (0)