Home >Backend Development >Python Tutorial >Concurrency Patterns: Balking Pattern
The Balking Design Pattern is a behavioral design pattern used to manage state-dependent actions in a system. It ensures that operations are executed only when the system is in an appropriate state. If the required precondition is not met, the operation is aborted or the system "balks". For those like me, who don't know what Balking is, this is what google has to say about it: "hesitate or be unwilling to accept an idea or undertaking". This pattern is particularly useful in multithreaded environments or systems where invalid actions could cause conflicts or errors.
Balking pattern is also considered more of an anti-pattern than a design pattern by some people in the community. If an object cannot support its API, it should either limit the API so that the offending call is not available, or so that the call can be made without limitation. This is an old pattern which seems to have arisen when JVMs were slower and synchronization wasn't as well understood and implemented as it is today. Regardless it is worth discussing and whether to use it or not is upto the developers.
Let's understand these with an example:
A printing system demonstrates the Balking Pattern:
Note: Yeah, we can handle this using a queue, but let's assume for now we don't know that such an elegant data structure exists.
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()
Looking at the code we can see that if we send a print request start_printing to the printer and the printer is busy it will check it's current state self.state and if the state is "printing", it will return without doing anything. Otherwise, it will take up that request and adjust its state accordingly.
The Balking Design Pattern provides an effective way to manage state-dependent actions and prevent invalid operations in software systems. By introducing clear guard conditions and ensuring thread safety, it enhances the reliability and maintainability of the system. Whether it's preventing multiple trips in a cab booking system or managing concurrent print jobs, the Balking Pattern offers a structured approach to avoid conflicts and maintain operational integrity. Ultimately, the choice to use the Balking Pattern depends on the specific requirements of your application and its concurrency needs.
The above is the detailed content of Concurrency Patterns: Balking Pattern. For more information, please follow other related articles on the PHP Chinese website!