Understanding Race Conditions in Swift with a Ticket Booking Example
Shashi Kumar Gupta
Senior Software Engineer | iOS | 8+ Years of experience | Swift | SwiftUI | Xcode | 50+ Projects Delivered | Cornerstone OnDemand | Pairroxz Technologies | JPLoft Solutions Pvt. Ltd
A race condition is a very unpredictable behavior in a system. Sometimes it behaves correctly, while at other times, it behaves unexpectedly. Let's take an example to illustrate this.
Scenario
Suppose there are four people named Shashi, Vishal, Yatin, and Rahul. They all want to book show tickets at the same time, but only 5 tickets are available. Let's assume Shashi wants 2 tickets, Vishal wants 3 tickets, Yatin needs 4 tickets, and Rahul wants 1 ticket. If they all try to book at the same time, some may get tickets while others may not, or someone may end up with tickets that are not actually available.
class PostViewModel: ObservableObject {
var availableTickets: Int = 5
private var concurrentQueue = DispatchQueue(label: "com.sample.learning.tickets", attributes: .concurrent)
var tickets = [
Person(ticketNumber: 2, name: "Shashi"),
Person(ticketNumber: 3, name: "Vishal"),
Person(ticketNumber: 4, name: "Yatin"),
Person(ticketNumber: 1, name: "Rahul")
]
func raceConditionHandling() {
for ticket in tickets {
concurrentQueue.async(flags: .barrier) {
self.bookTickets(person: ticket)
}
}
}
private func bookTickets(person: Person) {
print("Booking ticket is started for \(person.name)")
sleep(1)
if self.availableTickets >= person.ticketNumber {
self.availableTickets -= person.ticketNumber
print("Ticket allotted successfully for \(person.name)")
} else {
print("Ticket booking failed for \(person.name)")
}
}
}
struct Person {
var ticketNumber: Int
var name: String
}
Explanation
The?'raceConditionHandling'?function iterates over the list of people who want to book tickets. The?concurrentQueue.async(flags: .barrier)?line ensures that ticket booking operations are executed one at a time. The barrier flag ensures that the queue waits for the currently executing block to complete before starting the next one, thus preventing race conditions.
Log Output
From the logs, the output will look like this:
领英推荐
Booking ticket is started for Shashi
Ticket allotted successfully for Shashi
Booking ticket is started for Vishal
Ticket allotted successfully for Vishal
Booking ticket is started for Yatin
Ticket booking failed for Yatin
Booking ticket is started for Rahul
Ticket booking failed for Rahul
Before Booking Tickets
After Booking Tickets
Summary
By using Dispatch Barrier in Swift, we can avoid race conditions in iOS development. The barrier ensures that only one booking operation is processed at a time, thereby maintaining the consistency and integrity of the available tickets.
This approach provides a reliable solution to manage concurrent operations and prevent the unpredictable behavior associated with race conditions.
Android Engineer | 5+ year Experience | Android SDK | Kotlin | Java | Jetpack Compose
7 个月Very informative