Synchronization experiment of operating system processes

1. Experimental purpose

(1) Master the basic concepts and properties of processes and threads;

(2) Implement multi-threaded ticketing: simulate multiple ticketing windows (there are 2 windows here), and each window can sell tickets at the same time. Through multi-threading, ticketing operations can be performed concurrently to ensure thread safety;

(3) Provide user interface: Create a graphical user interface (GUI) to enable users to easily browse different routes, view flight information, select flights, enter the ticket quantity and select the ticket window;

2. Experimental content

Design a ticket sales program that simulates several ticket sales outlets. The interface can be referred to Figure 1. Multiple background ticketing threads should also be designed to run concurrently.

3. Algorithm design

This experiment involves multi-threaded concurrent processing of ticketing operations, so a synchronization mechanism needs to be used to ensure data consistency and thread safety. The global variable routes is used in the code to represent the flight information of different routes. Multiple threads can try to sell tickets at the same time, so a thread lock is needed to ensure that only one thread can modify the routes data structure at the same time.

The following is the design of the process synchronization algorithm:

1. Thread lock: The code uses a global lock variable as a thread lock. With lock is used to ensure that only one thread can access and modify the routes variable when processing ticket sales operations. This ensures mutual exclusivity of ticketing operations, preventing multiple threads from modifying the same data at the same time.

2. Ticket selling function ( sell_tickets ): This function is responsible for the actual ticket selling operation. Before selling the ticket, it first acquires the thread lock to ensure that only one thread can enter before entering the critical section. It then checks to see if there are enough seats left on the flight and, if so, modifies the data in routes to reflect the ticketing operation. Finally, the thread lock is released to allow other threads to enter the critical section.

3. Start of ticket selling thread (start_selling): This function is used to create and start the ticket selling thread. Each time a ticket purchase request is triggered, a new thread will be created to perform the ticket sales operation.

4. Query route function (query_route): When querying routes, multiple threads will also access routes data. However, because the ticketing operation uses thread locks, multiple threads can query route information at the same time without interfering with each other.

5. GUI event processing function: In the ticket purchase button click event and the route query button click event, access to routes data is involved. However, due to the use of thread locks, these event processing functions can also run in a multi-threaded environment to ensure Data consistency and thread safety.

In short, by using thread locks, this code ensures that the ticketing operation in a multi-threaded environment is thread-safe and avoids data competition and data inconsistency. Each thread needs to acquire the lock before selling tickets and then release the lock after completing the ticket selling operation. This synchronization mechanism ensures data integrity.

4. Operation and testing

Figure 2 Main interface of ticketing system

Figure 3 Use 1 window to purchase tickets

Figure 4 Use 2 windows to purchase tickets

Figure 5 Interface of insufficient remaining votes

5. Summary and thoughts

Through this experiment, I gained an in-depth understanding of the development of graphical user interface (GUI) applications and the practical application of multi-threaded programming. The following is my summary and experience in this experiment:

1. The importance of multi-threaded concurrent programming: In this experiment, I deeply realized the importance of multi-threaded concurrent programming. In this experiment, I simulated multiple ticketing windows, each window being an independent thread. This concurrent programming method allows different windows to perform ticket sales operations at the same time, improving the efficiency and responsiveness of the program. However, it also brings thread safety challenges, so thread locks are needed to ensure that conflicts do not occur when multiple threads access shared resources. This is an important programming skill that is critical for applications that require multiple tasks to be handled simultaneously.

2. The necessity of thread synchronization: In multi-threaded programming, thread synchronization is crucial. Different threads may access shared resources simultaneously, leading to data races and erratic behavior without proper synchronization mechanisms. Using thread locks is an effective way to ensure thread safety. It can prevent multiple threads from modifying shared resources at the same time and ensure data consistency.

3. The challenge of race conditions: Through this experiment, I learned that race conditions are a common problem in multi-threaded programming. When multiple threads attempt to modify a shared resource simultaneously, unexpected results may result. Therefore, code must be designed and written carefully to avoid race conditions.

4. User-friendly feedback: During the experiment, I learned how to provide user-friendly feedback and error handling. This is crucial to the user experience, the user should clearly understand what went wrong and know how to fix it. This also includes providing users with friendly prompts for insufficient information or invalid input so that they can better interact with the application.

In general, through this experiment, I not only learned the theoretical knowledge of multi-threaded concurrent programming, but also applied it to actual projects. I gained a better understanding of the complexities and potential challenges of multi-threaded programming, and how to ensure program stability and correctness through appropriate synchronization mechanisms. This knowledge and experience will be very helpful in my future programming work and projects, and I look forward to continuing to study and apply these skills in depth.

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import threading

#Initialize route and shift data (sample data)
routes = {
    "Guangzhou South-> Shenzhen North": [("A1", "09:00", 20, 50.0), ("A2", "11:30", 15, 45.0 )],
    "Guangzhou South-> Zhanjiang West": [("B1", "10:15", 30, 60.0), ("B2", "13:45", 25, 55.0 )],
    "Jiangmen->Guangzhou South": [("C1", "10:15", 45, 60.0), ("C2", "13:45", 66, 55.0) , ("C3", "13:45", 66, 55.0)],
    "Guangzhou South-> Shanwei": [("D1", "10:15", 57, 60.0), ("D2", "13:45", 38, 55.0) , ("D3", "13:45", 66, 55.0)],
    #Add more route and flight information
}

# Initialize the number of ticket windows
num_ticket_windows = 2

# Create a thread lock to ensure thread safety
lock = threading.Lock()

#Ticketing function
def sell_tickets(route, window_id, selected_class, num_tickets):
    global routes
    with lock:
        for i, (class_name, time, remaining_seats, price) in enumerate(routes[route]):
            if class_name == selected_class:
                if remaining_seats >= num_tickets:
                    routes[route][i] = (class_name, time, remaining_seats - num_tickets, price)
                    message = f"{window_id} sold {num_tickets} tickets for {class_name} flight, remaining tickets: {remaining_seats - num_tickets}"
                    show_message("Ticket sales successful", message)
                else:
                    show_message("Ticket sales failed", f"Window {window_id} cannot sell {num_tickets} tickets for {class_name} flight, and there are not enough tickets left")
                break

#Create a function to start the ticketing thread
def start_selling(route, window_id, selected_class, num_tickets):
    thread = threading.Thread(target=sell_tickets, args=(route, window_id, selected_class, num_tickets))
    thread.start()

# Function to query routes
def query_route():
    selected_route = route_combobox.get()
    tree.delete(*tree.get_children())

    if selected_route in routes:
        for class_name, time, remaining_seats, price in routes[selected_route]:
            tree.insert("", "end", values=(class_name, time, remaining_seats, price))
    else:
        show_message("Route not found", "The route information was not found")

#Create message prompt box
def show_message(title, message):
    messagebox.showinfo(title, message)

# Create GUI interface
root = tk.Tk()
root.title("Ticketing Program")

# Set window size
root.geometry("825x560")

# Before creating the GUI interface, add the following code to configure the style of Treeview
style = ttk.Style()
style.configure("Treeview.Heading", anchor="center", font=("Helvetica", 16)) # Set the header text to be centered and the font size to 16
style.configure("Treeview", rowheight=25, font=("Helvetica", 16)) # Set the row height and font size to 16

#Create a route selection drop-down box
route_label = tk.Label(root, text="Select route:", font=("Helvetica", 16)) # Set the font size to 16
route_label.grid(row=1, column=0, padx=10, pady=10)
route_combobox = ttk.Combobox(root, values=list(routes.keys()), font=("Helvetica", 16)) # Set the font size to 16
route_combobox.grid(row=1, column=1, padx=10, pady=10)

#Create a query route button
query_button = tk.Button(root, text="query route", command=query_route, font=("Helvetica", 16)) # Set the font size to 16
query_button.grid(row=1, column=2, padx=10, pady=10)

#Create a table to display shift information
columns = ("shift", "time", "remaining tickets", "price")
tree = ttk.Treeview(root, columns=columns, show="headings")
for col in columns:
    tree.heading(col, text=col)
    tree.column(col, anchor="center") # Set the text in the column to be centered
    tree.heading(col, text=col, anchor="center") # Set the header text to be centered
tree.grid(row=2, column=0, columnspan=3, padx=10, pady=10)

# Create purchase ticket input box and purchase button
ticket_count_label = tk.Label(root, text="Number of tickets purchased:", font=("Helvetica", 16)) # Set the font size to 16
ticket_count_label.grid(row=3, column=0, padx=10, pady=10)
ticket_count_entry = tk.Entry(root, font=("Helvetica", 16)) # Set the font size to 16
ticket_count_entry.grid(row=3, column=1, padx=10, pady=10)

# Ticket window button
window1_button = ttk.Button(root, text="1Window", command=lambda: purchase_tickets("Window1"), style="TButton") # Set style
window1_button.grid(row=4, column=0, padx=(2, 10), pady=10) # Change the second parameter of padx to 10

window2_button = ttk.Button(root, text="2Window", command=lambda: purchase_tickets("Window2"), style="TButton") # Set style
window2_button.grid(row=4, column=2, padx=(10, 2), pady=10) # Change the first parameter of padx to 10

# Create a new ttk Style to set the button font size
button_style = ttk.Style()
button_style.configure("TButton", font=("Helvetica", 16))

# Ticket purchase function
def purchase_tickets(selected_window):
    selected_route = route_combobox.get()
    selected_item = tree.selection()
    num_tickets_str = ticket_count_entry.get()

    if not selected_route:
        show_message("Please select a route", "Please select a route to purchase.")
        return
    if not selected_item:
        show_message("Please select the flight", "Please select the flight you want to purchase.")
        return
    if not num_tickets_str:
        show_message("Please enter the number of votes", "Please enter the number of tickets to be purchased.")
        return

    selected_class = tree.item(selected_item)["values"][0]
    num_tickets = int(num_tickets_str)

    if selected_route and selected_class and num_tickets > 0:
        start_selling(selected_route, selected_window, selected_class, num_tickets)
        query_route() # Update the displayed shift information

#Create a headline
title_label = tk.Label(root, text="Train Ticket Sales System", font=("楷体", 35, "bold"))
title_label.grid(row=0, column=0, columnspan=3, padx=10, pady=20)

root.mainloop()

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Python entry skill treeHomepageOverview 389058 people are learning the system