Implementing Thread Synchronization in Java
Java provides synchronization mechanisms to prevent resource access conflicts in multi-threaded applications.
- Thread Safety Issues
Real-world applications like banking systems or ticket booking systems often encounter problems when multiple threads access shared resources simultaneously. Consider a ticket booking system where two threads check remaining tickets at the same time when only one ticket remains. Both threads might proceed to sell the ticket, resulting in negative counts.
class TicketSystem implements Runnable {
int availableTickets = 10;
public void run() {
while (true) {
if (availableTickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Selling ticket " + availableTickets--);
}
}
}
public static void main(String[] args) {
TicketSystem system = new TicketSystem();
new Thread(system).start();
new Thread(system).start();
new Thread(system).start();
}
}
This implementation demonstrates the race condition problem where multiple threads can sell the same ticket.
- Synchronization Mechanisms
Java offers two primary apporaches to handle thread synchronization:
(1) Synchronized Blocks
synchronized(lockObject) {
// critical section
}
Example implementation:
class SafeTicketSystem implements Runnable {
int availableTickets = 10;
Object lock = new Object();
public void run() {
while (true) {
synchronized (lock) {
if (availableTickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Selling ticket " + availableTickets--);
}
}
}
}
}
(2) Synchronized Methods
public synchronized void processTicket() {
// critical section
}
When a thread enters a synchronized method, other threads must wait until the current thread completes execution of the method.