序列化期间更新Java对象是否安全?以java.util.HashMap为例
序列化期间更新对象的安全性问题(以HashMap为例)
结论:序列化期间并发更新非线程安全对象(比如java.util.HashMap)完全不安全,一定会存在序列化结果损坏的风险。
具体到HashMap的场景:
HashMap本身是非线程安全的,内部没有任何同步逻辑来保障多线程操作下的状态一致性。- 查看
HashMap.writeObject的源码会发现,它直接遍历内部的table数组、读取size等字段来完成序列化。如果此时有另一个线程同时执行put、remove或扩容操作,会出现以下问题:- 遍历到的链表/红黑树可能处于半修改状态,包含无效的节点引用
size字段的值和实际存在的元素数量不匹配- 扩容过程中
table数组的引用被替换,导致序列化到一半的数组失效
- 最终序列化后的内容要么数据残缺、要么包含逻辑错误的状态,反序列化时可能抛出异常,或者得到一个不符合预期的HashMap实例。
通用原则:
- 所有非线程安全对象,在序列化过程中如果被并发修改,都会出现类似的一致性问题。序列化本质是对对象当前状态的快照,并发修改会让快照捕获到中间的无效状态。
- 如果必须在多线程环境下序列化HashMap,有两种可行方案:
- 用
synchronized块包裹序列化代码,确保序列化期间没有其他线程修改对象 - 使用
Collections.synchronizedMap()包装HashMap,借助同步包装类的线程安全保障
- 用
内容的提问来源于stack exchange,提问作者Fredrik LS
相关产品推荐
相关产品推荐

