0

0

并发模式:犹豫模式

DDD

DDD

发布时间:2024-12-25 11:39:01

|

710人浏览过

|

来源于dev.to

转载

简介

犹豫设计模式是一种行为设计模式,用于管理系统中依赖于状态的操作。它确保只有当系统处于适当的状态时才执行操作。如果不满足所需的先决条件,则操作将中止或系统“犹豫”。对于像我这样不知道什么是 balking 的人来说,谷歌对此是这么说的:“犹豫或不愿意接受一个想法或承诺”。此模式在无效操作可能导致冲突或错误的多线程环境或系统中特别有用。

社区中的一些人还认为,犹豫模式更多的是一种反模式,而不是设计模式。如果一个对象不能支持它的 api,它应该限制 api 以使有问题的调用不可用,或者使调用可以不受限制地进行。这是一种古老的模式,似乎是在 jvm 速度较慢并且同步不像今天那样被充分理解和实现时出现的。不管怎样,它值得讨论,是否使用它取决于开发者。

犹豫模式依赖于三个基本概念

  1. 保护条件:操作继续进行必须满足的条件。
  2. 状态相关操作:依赖于系统当前状态的操作。
  3. 线程安全:该模式经常使用锁或其他同步机制来确保并发环境中的安全。

让我们通过一个例子来理解这些:

打印系统演示了犹豫模式:

  • 场景:一台打印机一次只能处理一个打印请求。即使多个进程可以发出打印请求。
  • guard condition:打印不得主动“打印”来处理新的打印请求。
  • 行为:如果打印机正忙,系统会犹豫不决,不会继续处理新的打印请求。

注意:是的,我们可以使用队列来处理这个问题,但我们现在假设我们不知道存在这样一个优雅的数据结构。

千帆大模型平台
千帆大模型平台

面向企业开发者的一站式大模型开发及服务运行平台

下载
import threading
import time

class Printer:
    def __init__(self):
        self.state = "idle"
        self.lock = threading.Lock()

    def start_printing(self, job_id):
        print(f"Attempting to start Print Job {job_id}...")

        with self.lock:  # Ensure thread safety
            if self.state == "printing":
                print(f"Balking: Print Job {job_id} cannot start. Printer is busy.")
                return
            self.state = "printing"

        # Simulate the printing process
        print(f"Print Job {job_id} started.")
        time.sleep(3)
        print(f"Print Job {job_id} completed.")

        with self.lock:
            self.printing = "idle"

# Multiple threads attempting to start print jobs
printer = Printer()

threads = [
    threading.Thread(target=printer.start_printing, args=(1,)),
    threading.Thread(target=printer.start_printing, args=(2,))
]

for t in threads:
    t.start()

for t in threads:
    t.join()

查看代码我们可以看到,如果我们向打印机发送打印请求 start_printing 并且打印机正忙,它将检查其当前状态 self.state,如果状态为“正在打印”,它将返回而不执行任何操作。否则,它将接受该请求并相应地调整其状态。

何时使用犹豫模式

  1. 多线程系统:防止竞争条件或无效操作。
  2. 与状态相关的工作流程:仅在某些状态下才允许执行操作。
  3. 资源管理:防止共享资源的不当使用。 使用这种模式的对象通常只处于一种容易暂时停滞的状态,但持续时间未知。如果对象要在已知的有限时间内保持在容易犹豫的状态,那么保护悬挂模式可能是首选。

犹豫模式的优点

  1. 防止无效操作:警卫确保操作仅在有效条件下发生。
  2. 线程安全:在多线程系统中特别有用。
  3. 简化逻辑:将依赖于状态的操作封装成清晰、可重用的模式。

缺点

  1. 有限的适用性:当操作是二进制的(允许或不允许)时最有用。
  2. 潜在开销:防护检查和同步机制可能会带来性能成本。

结论

犹豫设计模式提供了一种有效的方法来管理状态相关的操作并防止软件系统中的无效操作。通过引入明确的保护条件并保证线程安全,增强了系统的可靠性和可维护性。无论是防止出租车预订系统中的多次行程还是管理并发打印作业,balking 模式都提供了一种结构化方法来避免冲突并保持操作完整性。最终,选择使用犹豫模式取决于应用程序的具体要求及其并发需求。

参考文献

  • 维基百科 - 犹豫模式
  • ucb

相关专题

更多
treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

533

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

12

2026.01.06

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

479

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

143

2025.12.24

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

50

2026.01.09

c++框架学习教程汇总
c++框架学习教程汇总

本专题整合了c++框架学习教程汇总,阅读专题下面的文章了解更多详细内容。

28

2026.01.09

学python好用的网站推荐
学python好用的网站推荐

本专题整合了python学习教程汇总,阅读专题下面的文章了解更多详细内容。

90

2026.01.09

学python网站汇总
学python网站汇总

本专题整合了学python网站汇总,阅读专题下面的文章了解更多详细内容。

10

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
550W粉丝大佬手把手从零学JavaScript
550W粉丝大佬手把手从零学JavaScript

共1课时 | 0.2万人学习

尚硅谷JavaScript高级视频教程
尚硅谷JavaScript高级视频教程

共48课时 | 14.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号