Java中的共享资源与并发安全问题
发布时间 - 2026-01-06 00:00:00 点击率:次ArrayList线程不安全因其方法无同步控制,多线程并发add可能引发扩容竞态,导致ArrayIndexOutOfBoundsException、数据丢失或ConcurrentModificationException。
为什么多个线程访问同一个 ArrayList 会出错
因为 ArrayList 不是线程安全的:它的 add()、remove()、get() 等方法内部没有同步控制。当两个线程同时调用 add(),可能触发底层数组扩容,而扩容过程涉及新建数组、复制元素、更新引用——若此时另一个线程正在读或写旧数组,就会出现 ArrayIndexOutOfBoundsException、数据丢失或 ConcurrentModificationException。
常见现象包括:集合大小比预期小、遍历时抛 ConcurrentModificationException、偶发 NullPointerException(因元素未完全写入)。
- 不要在多线程环境中直接共享裸
ArrayList、HashMap、HashSet - 如果只读不写,且初始化完成后不再修改,可用
Collections.unmodifiableList()包装 - 若需读多写少,优先考虑
CopyOnWriteArrayList;但注意它每次写操作都复制整个数组,不适合高频写场景
如何正确使用 synchronized 保护临界区
加锁本身不难,关键在于锁对象是否一致、粒度是否合理。错误做法是给每个方法加 synchronized,却用不同锁(如 this vs getClass()),导致实际没互斥。
典型问题:对共享资源的读写必须使用同一把锁;锁范围应刚好覆盖所有依赖该资源的操作,过大会降低并发度,过小则失去保护。
立即学习“Java免费学习笔记(深入)”;
- 实例方法上加
synchronized,等价于用this作锁;静态方法加synchronized,等价于用MyClass.class作锁 - 若需细粒度控制(例如只锁某个字段),显式使用
synchronized(lockObj),且确保所有访问路径都用同一个lockObj - 避免在同步块内调用外部可重入的方法(如回调、I/O),以防死锁或锁持有时间过长
ReentrantLock 比 synchronized 多了什么
ReentrantLock 提供更灵活的锁控制能力,但不是“更高级就该默认用它”。它适合需要尝试获取锁、可中断等待、或按特定顺序释放多个锁的场景。
容易忽略的点:ReentrantLoc 必须手动
klock() 和 unlock(),且 unlock() 必须放在 finally 块中;否则一旦异常跳出,锁永远无法释放。
- 用
lock.tryLock()可避免无限等待,适合超时控制或避免死锁检测 -
lock.lockInterruptibly()允许线程被interrupt()中断,而synchronized不响应中断 - 不要在
ReentrantLock的lock()和unlock()之间跨方法调用,除非你明确掌控整个调用链的异常路径
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// 访问共享资源
} finally {
lock.unlock(); // 必须放在这里
}
原子变量(AtomicInteger 等)能替代锁吗
能,但仅限于单个变量的简单操作,比如计数器、状态标志、序列号生成。它们底层依赖 CPU 的 CAS(Compare-And-Swap)指令,无锁且高效。
不能替代锁的场景:多个变量需要保持一致性(如银行转账:从 A 扣款 + 给 B 加款),或操作逻辑复杂(如先查再改再存),这时 CAS 无法保证整体原子性。
-
AtomicInteger的incrementAndGet()是原子的;但i++(即get() + 1再set())不是,必须用原子方法 - 注意
lazySet()和set()的内存语义差异:lazySet()不保证后续读操作立即看到,适合写后极少读的场景(如统计上报) - 不要试图用多个原子变量拼出复合操作的安全性——这通常意味着你需要真正的锁或事务机制
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel怎么实现验证码(Captcha)功能
如何在阿里云高效完成企业建站全流程?
北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?
使用豆包 AI 辅助进行简单网页 HTML 结构设计
如何用PHP工具快速搭建高效网站?
Linux系统命令中tree命令详解
Laravel distinct去重查询_Laravel Eloquent去重方法
深入理解Android中的xmlns:tools属性
如何在香港服务器上快速搭建免备案网站?
教学论文网站制作软件有哪些,写论文用什么软件
?
Laravel如何处理异常和错误?(Handler示例)
javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】
如何在HTML表单中获取用户输入并用JavaScript动态控制复利计算循环
公司网站制作需要多少钱,找人做公司网站需要多少钱?
Laravel如何升级到最新的版本_Laravel版本升级流程与兼容性处理
HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】
如何在云虚拟主机上快速搭建个人网站?
使用PHP下载CSS文件中的所有图片【几行代码即可实现】
如何快速搭建虚拟主机网站?新手必看指南
如何在云主机快速搭建网站站点?
高防服务器租用指南:配置选择与快速部署攻略
车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?
宙斯浏览器视频悬浮窗怎么开启 边看视频边操作其他应用教程
如何续费美橙建站之星域名及服务?
jQuery中的100个技巧汇总
EditPlus中的正则表达式 实战(1)
C++时间戳转换成日期时间的步骤和示例代码
微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】
如何快速搭建高效服务器建站系统?
php静态变量怎么调试_php静态变量作用域调试技巧【解答】
手机网站制作与建设方案,手机网站如何建设?
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
七夕网站制作视频,七夕大促活动怎么报名?
如何快速生成可下载的建站源码工具?
Laravel怎么实现模型属性的自动加密
实例解析angularjs的filter过滤器
在Oracle关闭情况下如何修改spfile的参数
Python自动化办公教程_ExcelWordPDF批量处理案例
如何在新浪SAE免费搭建个人博客?
Laravel怎么实现支付功能_Laravel集成支付宝微信支付
如何选择PHP开源工具快速搭建网站?
html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】
胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?
html5audio标签播放结束怎么触发事件_onended回调方法【教程】
详解Huffman编码算法之Java实现
如何快速搭建高效WAP手机网站?
php在windows下怎么调试_phpwindows环境调试操作说明【操作】
Laravel如何与Inertia.js和Vue/React构建现代单页应用
rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted
如何快速重置建站主机并恢复默认配置?

