从0开始理解并发、线程与等待通知机制(下)

发布时间:2026/6/20 14:11:50

从0开始理解并发、线程与等待通知机制(下) 线程安全问题与synchronized机制线程安全问题演示示例类SynTest定义一个count变量。启动两个线程对count进行累加操作预期结果为2万。实际运行结果小于2万且不稳定表明线程不安全。原因分析多线程同时访问共享变量导致不可预料的结果。解决方案使用synchronized关键字加锁。synchronized使用方式方法级别加锁在方法返回值前添加synchronized关键字。该锁对象为当前实例this。代码块加锁使用synchronized(this)或synchronized(obj)指定锁对象。更灵活适用于部分代码加锁场景。对象锁与类锁的区别对象锁用于成员方法或同步块中锁对象为具体实例如this或任意Object。类锁用于静态方法或锁住类的class对象。关键原则多个线程必须持有同一把锁才能实现互斥访问共享资源。错误使用synchronized案例若两个线程分别使用不同的锁对象如new Object()则无法保证线程安全。必须确保多个线程使用的锁对象是同一个。volatile关键字详解应用场景适用于一写多读的并发场景。例如主线程修改某个标志位其他线程感知变化并作出响应。作用与限制可见性一个线程对变量的修改对其他线程立即可见。有序性防止指令重排序优化。不能保证原子性无法替代synchronized或AtomicInteger等原子类。为何不是锁机制volatile仅提供轻量级通信与同步机制无加锁过程。不具备互斥能力不能解决多线程同时写共享变量的安全问题。字节码层面解释对于Integer count变量每次count都会创建新的Integer对象。导致即使加锁也可能因锁对象变化而失效。可通过打印哈希码验证对象地址是否变化。volatile vs synchronizedsynchronized既能保证可见性又能保证原子性和有序性。volatile只能保证可见性和有序性。等待通知机制标准范式生活类比快递通知机制类似快递到达驿站后系统发短信通知用户取件。避免轮询浪费资源。核心APIObject类中的wait与notifywait()使线程进入等待状态释放锁。notify()/notifyAll()唤醒一个或所有等待线程。必须在synchronized块中调用否则抛出异常。标准范式等待方javasynchronized(锁对象) { while (条件不满足) { 锁对象.wait(); } // 条件满足继续执行业务逻辑 }通知方javasynchronized(锁对象) { // 修改条件 锁对象.notifyAll(); }注意事项wait()会释放锁notify()不会立即释放锁需等到同步块执行完毕。必须在while循环中检查条件避免虚假唤醒。实战案例模拟快递运输与连接池快递运输案例主线程模拟快递运输每增加100公里唤醒一次。子线程监听公里数变化更新数据库另一子线程监听是否到达目的地并通知用户。连接池实现使用等待通知机制管理数据库连接池。支持超时等待模式增强灵活性。核心思想空闲时等待有连接可用时通知唤醒。等待超时模式实现记录超时时间戳。每次被唤醒后重新计算剩余等待时间。时间归零则退出等待抛出异常。面试高频题解析线程相关方法与锁的关系sleep()不释放锁。yield()不释放锁。wait()释放锁。notify()/notifyAll()不释放锁同步块执行完才释放。为什么wait/notify必须在同步块中调用避免lost wake-up问题。若不在同步块中调用可能导致通知丢失线程永远阻塞。为什么要在while中检查条件多线程环境下可能出现虚假唤醒。使用while循环确保条件真正满足后再继续执行。补充知识CompletableFuture背景JDK1.8引入用于简化Future任务编排。支持链式调用、组合任务、异步处理等。核心功能任务编排支持任务之间的依赖关系thenApply, thenAccept等。异步执行支持自定义线程池。组合任务allOf, anyOf等。接口结构CompletableFutureT实现了FutureT和CompletionStageT接口。提供丰富API用于任务控制和组合。答疑总结关于notify与notifyAllnotify()随机唤醒一个等待线程。notifyAll()唤醒所有等待线程。实际开发中更推荐使用notifyAll()避免遗漏唤醒目标线程。CompletableFuture是否能替代线程池不能完全替代它只是任务编排工具。仍需线程池执行实际任务。同步机制的本质同步即协调多个线程按顺序访问共享资源。synchronized和volatile均可实现同步但侧重点不同。volatile如何保证可见性插入内存屏障刷新CPU缓存到主存。所有读线程均可看到最新值。类锁能否继承不可以锁是基于对象或class对象不具有继承特性。

相关新闻