3 分钟阅读
ConcurrentHashMap 计数:别把 get 加 put 当原子操作
使用了并发 Map,却仍然出现计数丢失,因为“读取旧值再写入新值”是两个独立操作。容器安全与业务更新原子性并不等价。
使用了并发 Map,却仍然出现计数丢失,因为“读取旧值再写入新值”是两个独立操作。容器安全与业务更新原子性并不等价。
持锁过程中业务抛异常,后续线程就一直等待,通常是因为 unlock 没有放进 finally。同步代码同样需要异常安全。
调用 interrupt 后,工作线程未必立刻退出。中断不是强制终止,而是让被调用方有机会检查或响应取消。
连接对方服务器很快,不代表对方会及时返回响应。只有连接超时,不能完整约束一次请求的等待时间。
异步调用失败后,有的方法会把异常转成默认值,有的方法仅观察结果。混用会让上层误以为失败已经被正确处理。
停止标志需要被另一个线程看到,但计数器需要防止更新丢失。这两种共享变量问题不应该使用同一个答案。
多个线程对普通 int 执行 ++,可能丢失更新。即便替换成 AtomicInteger,先判断再增加的业务流程也不一定安全。
Integer 是 Number 的子类,但把 List<Integer> 交给接受 List<Number> 的方法会编译失败。集合如果同时允许读写,简单的类型替换会破坏安全性。
把用户列表转成 Map 时,同一个业务 ID 出现两次,收集过程可能抛异常。重复数据究竟应该覆盖、合并还是拒绝,需要显式决定。
在 map 里加了打印语句,程序却没有输出,可能不是数据为空,而是流水线尚未被消费。
用户输入一个点号,本想精确搜索点号,却匹配了任意字符。把外部文本直接拼进正则,会改变匹配规则。
同一文件在开发机正常,在另一台机器上出现乱码,往往是因为依赖了隐含字符集或文件来源没有约定编码。