Lab 6: Race Conditions and Blocking Queue

In this lab, you will explore concurrent programming challenges by tackling race conditions in a ticket booking system. You’ll learn how to identify and solve thread safety issues in real-world applications.

Objectives

  • Identify the critical section that results in race conditions in multi-threaded environments.
  • Apply synchronization techniques to protect shared resources in multi-threaded environments.
  • Implement a thread-safe publisher-subscriber application.
  • Gain practical experience with the publisher-subscriber design pattern in concurrent applications.
  • Understand the importance of thread safety issues in real-world scenarios like booking and notification systems.

Introduction

A software engineer is working for a transportation company that needs to handle concurrent ticket booking requests for train journeys. The current implementation has a critical flaw: when multiple users try to book tickets simultaneously, they sometimes end up with the same seat number, leading to customer complaints and operational issues.

Additionally, the company has implemented a notification system where booking events are published to multiple subscribers (like email service, SMS service, analytics system), but the current implementation has issues with event loss and system instability under load.

In this lab, you will step into the role of this software engineer. First, you will identify and fix race conditions in the ticket booking system. Then, you will fix the the publisher-subscriber system and improve it using Java’s BlockingQueue to ensure thread-safe communication between components.

This hands-on activity should provide you with a practical experience on fixing problems in concurrency.

Prerequisites

  • Java Development Kit (JDK) 17 or later
  • Your preferred Java IDE (IntelliJ IDEA or VS Code)
  • Git for version control

Getting Started

If your instructor is using GitHub classroom, you will need to accept the assignment using the link at the bottom of this page, clone your auto-generated repository, and import it as a project into your IDE.

If your instructor is not using GitHub classroom, clone and import the template project at https://github.com/cpit305-spring-25-IT1/lab-06 ↗.

Task 1: Fixing Race Conditions in Ticket Booking System

The train company’s customer service department has reported a critical issue: passengers are arriving at their seats only to find someone else with a ticket showing the exact same seat number. This has led to customer disputes, delays in departures, and damage to the company’s reputation.

After investigating the issue, the operations team identified the problem as a software defect and escalated it through the IT department to the development team. As a software engineer on this team, you’ll need to diagnose and fix the underlying concurrency issue in the ticketing system.

Looking at the code, the system suffers from a classic race condition where multiple threads (representing simultaneous user booking requests) can view and reserve the same seat number when requests occur at nearly the same time. Your task is to identify the critical section in src/main/java/cpit305/fcit/kau/edu/sa/TicketBookingSystem.java and implement proper synchronization to eliminate this race condition.

TicketBookingSystem.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package cpit305.fcit.kau.edu.sa;

import java.util.*;

public class TicketBookingSystem {
    private static final int TOTAL_SEATS = 100;
    private Set<Integer> bookedSeats = new HashSet<>();
    
    /**
     * Books a seat for a passenger
     * @param passengerName Name of the passenger
     * @return The seat number that was booked, or -1 if no seats are available
     */
    public int bookSeat(String passengerName) {
        if (bookedSeats.size() >= TOTAL_SEATS) {
            return -1; // No seats available
        }
        
        // Find the first available seat
        int seatNumber = -1;
        for (int i = 1; i <= TOTAL_SEATS; i++) {
            if (!bookedSeats.contains(i)) {
                seatNumber = i;
                break;
            }
        }
        
        if (seatNumber != -1) {
            // Simulate processing time (might increase chance of race condition)
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            
            bookedSeats.add(seatNumber);
            System.out.println("Seat " + seatNumber + " booked for " + passengerName);
        }
        
        return seatNumber;
    }
    
    /**
     * Gets the total number of seats currently booked
     * @return The number of booked seats
     */
    public int getBookedSeatsCount() {
        return bookedSeats.size();
    }
    
    /**
     * Checks if a specific seat is booked
     * @param seatNumber The seat number to check
     * @return true if the seat is booked, false otherwise
     */
    public boolean isSeatBooked(int seatNumber) {
        return bookedSeats.contains(seatNumber);
    }
    
    /**
     * Resets the booking system by clearing all booked seats
     */
    public void reset() {
        bookedSeats.clear();
    }
}

Run the unit test at src/test/java/cpit305/fcit/kau/edu/sa/TicketBookingSystemTest.java to verify your implementation. The test simulates multiple threads trying to book tickets simultaneously and checks if any seat is booked more than once.

Deliverables and Submission

Please push your code to GitHub for auto-grading and submit a PDF file with:

  1. Screenshots showing your implementation