Understanding Race Conditions in Swift with a Ticket Booking Example

Understanding Race Conditions in Swift with a Ticket Booking Example


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

  • Available tickets: 5

After Booking Tickets

  • Shashi books 2 tickets: 3 tickets left
  • Vishal books 3 tickets: 0 tickets left
  • Yatin tries to book 4 tickets: fails
  • Rahul tries to book 1 ticket: fails


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.

Vishal Trivedi

Android Engineer | 5+ year Experience | Android SDK | Kotlin | Java | Jetpack Compose

7 个月

Very informative

要查看或添加评论,请登录

社区洞察

其他会员也浏览了