老废物乐园 瓜子的技术笔记 · Java / AI / 金融科技

InnoDB 行锁与间隙锁:一次死锁日志分析

凌晨两点的死锁告警 5 月 28 号凌晨,库存服务的告警响了:批量扣减任务报死锁,一晚上 217 次。错误是客户端收到的: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when t

遥望星星 遥望星星 发布于 2019-06-26

AQS 源码初探:ReentrantLock 是怎么实现的

jstack 里那个等了 40 秒的线程 5 月中旬,运营反馈大客户导出特别慢,一个 20 万行的订单导出要跑三分钟。我抓了几份 jstack,发现有个线程的行为很奇怪: "export-thread-7" #48 prio=5 os_prio=0 tid=0x00007f8c4c0d8000 ni

遥望星星 遥望星星 发布于 2019-06-19

ConcurrentHashMap 为什么比 synchronizedMap 快

压测报告里,那根最扎眼的柱子 一月初做订单履约服务的性能优化,主管让我把瓶颈点列一遍。用 JMH 跑了几个核心组件的基准测试,结果里最刺眼的是本地缓存这一项:同样 8 线程、读写比 9:1,Collections.synchronizedMap(new HashMap<>()) 的吞吐是 2.1M

遥望星星 遥望星星 发布于 2019-04-19

线程安全的单例模式该怎么写?双重检查锁与 volatile

面了三家公司,两次被问到"单例为什么要加 volatile" 十月中旬开始投简历试水,面试被问了三次单例模式。第一次我背出了双重检查锁的写法,面试官追问"为什么 instance 要加 volatile",我卡住了,说了句"保证可见性",他摇摇头。第二次还是同一个问题,我还是没答到点上。 回来自己翻

遥望星星 遥望星星 发布于 2019-03-12

synchronized 和 ReentrantLock 该怎么选

压测数据打脸:我把 synchronized 换成 ReentrantLock,反而慢了 8 月份做优惠券发放模块,有个扣库存的临界区。师傅说了句"ReentrantLock 比 synchronized 快",我就吭哧吭哧把代码全改了,还加了 finally 释放锁。结果自己压测一测,10 并发下

遥望星星 遥望星星 发布于 2019-02-16

ThreadLocal 内存泄漏:线程池里的脏数据从哪来

客服工单里的串号:A 用户看到了 B 用户的手机号 7 月初的一个下午,客服转过来一张截图:用户 A 在个人中心看到的手机号,是另一个用户的。我第一反应是不信,把那串号码脱敏后在库里一查,确实属于用户 B,两个人八竿子打不着。 我们那个接口长这样,用户信息是从一个 ThreadLocal 里取的,网

遥望星星 遥望星星 发布于 2019-02-06

SimpleDateFormat 非线程安全导致线上日期错乱复盘

客服说:订单创建时间显示成了 1970 年 5 月 14 号早上,客服群里转过来一张用户截图,订单详情里的创建时间是 1970-01-01 08:00:00。我第一反应是数据库存了 0,查了一下,数据库里的时间戳完全正常。 那就是显示的时候格式化错了。去看那段代码: @Service public

遥望星星 遥望星星 发布于 2019-01-23

volatile 到底解决了什么问题?可见性与指令重排

同事问我:既然有 volatile,为什么还要加锁 上周 code review,同事看到我写的一个状态标记用了 volatile,问我:"这东西不是能保证线程安全吗,那 synchronized 还有什么用?" 我说不能这么理解,但当时没能讲清楚。下来自己看了几天 JMM 的资料,又写了几个例子验

遥望星星 遥望星星 发布于 2019-01-16