状态依赖性的管理
可阻塞的状态依赖操作的形式如下:
- 构成前提条件的变量必须由对象的锁来保护, 从而使它们在测试前提条件的同时保持不变
- 如果前提条件未满足, 就必须释放锁, 以便其他线程可以修改锁的状态
- 在再次测试前提条件之前必须重新获取锁
有界缓存示例
有界缓存:
- put操作的前提条件是不能从空缓存中获取元素
- take操作的前提条件是不能往已满的缓存中放元素
将前提条件的失败传递给调用者
- 前提条件失败后进入休眠, 避免消耗过多的CPU时间, 但是响应性低
- 也可以重新调用take方法, 进入忙等待(也叫自旋等待), 但会消耗大量的CPU时间
- 也可以调用Thread.yield, 提示调度器, 让出一定的时间让另一个线程运行以提高效率
通过轮询和休眠来实现简单的阻塞
如下图, 将前提条件的管理操作封装了起来, 从而使调用者无须在每次调用时都实现重试逻辑, 简化了缓存的使用
条件队列
条件队列的名字来源于: 它使得一组线程(等待线程集合)能够通过某种方式来等待特定的条件变成真. 传统队列的元素是一个个数据, 而与之不同的是, 条件队列中的元素是一个个正在等待相关条件的线程
- Object.wait会自动释放锁, 并请求操作系统挂起当前线程, 从而使其他线程能够获得这个锁并修改对象的状态
- 条件队列使得在表达和管理状态依赖性时更加高效
使用条件队列
- 关键是找出对象在哪个条件谓词上等待, 条件谓词是使某个操作成为状态依赖操作的前提条件