Program 1: Bank Account Withdrawal
Multiple threads attempt to withdraw money from the same bank account simultaneously. A synchronized method ensures that only one thread can access the withdrawal operation at a time. The balance is checked before withdrawing money. This prevents invalid withdrawals and maintains the correct account balance.
class BankAccount {
private int balance = 10000;
public synchronized void withdraw(String name, int amount) {
if (balance >= amount) {
balance -= amount;
System.out.println(name + " withdrew: " + amount +
" | Remaining Balance: " + balance);
} else {
System.out.println(name + " cannot withdraw: " + amount +
" | Insufficient Balance");
}
}
}
class BankWithdrawalExample {
public static void main(String[] args) {
BankAccount account = new BankAccount();
Thread t1 = new Thread(() -> account.withdraw("User-1", 6000));
Thread t2 = new Thread(() -> account.withdraw("User-2", 5000));
t1.start();
t2.start();
}
}Execution and Output:
D:\test>javac BankWithdrawalExample.java
D:\test>java BankWithdrawalExample
User-1 withdrew: 6000 | Remaining Balance: 4000
User-2 cannot withdraw: 5000 | Insufficient Balance
Program 2: Online Ticket Booking
Multiple users attempt to book seats at the same time. A synchronized block protects the shared seat count. Only one thread can update the available seats at a time. This ensures that the same seat is not allocated more than once.
class TicketBooking {
private int availableSeats = 2;
public void bookTicket(String user, int seats) {
synchronized (this) {
if (availableSeats >= seats) {
availableSeats -= seats;
System.out.println(user + " booked " + seats +
" seat(s). Remaining: " + availableSeats);
} else {
System.out.println(user + " booking failed.");
}
}
}
}
class OnlineTicketBookingExample {
public static void main(String[] args) {
TicketBooking booking = new TicketBooking();
Thread t1 = new Thread(() -> booking.bookTicket("Ravi", 1));
Thread t2 = new Thread(() -> booking.bookTicket("Priya", 2));
t1.start();
t2.start();
}
}Execution and Output:
D:\test>javac OnlineTicketBookingExample.java
D:\test>java OnlineTicketBookingExample
Ravi booked 1 seat(s). Remaining: 1
Priya booking failed.Code language: CSS (css)
Program 3: Inventory Stock Management
An inventory is shared by multiple threads that add and purchase products. A synchronized instance method protects the stock quantity. This ensures that stock updates happen safely without lost changes. The inventory count remains consistent even when threads execute concurrently.
class Inventory {
private int stock = 10;
public synchronized void addStock(int quantity) {
stock += quantity;
System.out.println("Added: " + quantity + " | Stock: " + stock);
}
public synchronized void purchase(String customer, int quantity) {
if (stock >= quantity) {
stock -= quantity;
System.out.println(customer + " purchased: " + quantity +
" | Stock: " + stock);
} else {
System.out.println("Insufficient stock for " + customer);
}
}
}
class InventoryExample {
public static void main(String[] args) {
Inventory inventory = new Inventory();
Thread t1 = new Thread(() -> inventory.purchase("Customer-1", 6));
Thread t2 = new Thread(() -> inventory.addStock(5));
Thread t3 = new Thread(() -> inventory.purchase("Customer-2", 7));
t1.start();
t2.start();
t3.start();
}
}Execution and Output:
D:\test>javac InventoryExample.java
D:\test>java InventoryExample
Customer-1 purchased: 6 | Stock: 4
Insufficient stock for Customer-2
Added: 5 | Stock: 9
Program 4: Shared Web Request Counter
Multiple client threads increment a common request counter. A synchronized static method locks the class and protects the shared static variable. This prevents lost updates when many threads increment the counter. Every request is counted correctly.
class RequestCounter {
private static int count = 0;
public static synchronized void increment() {
count++;
}
public static synchronized int getCount() {
return count;
}
}
class WebRequestCounterExample {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
RequestCounter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
RequestCounter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Total Requests: " +
RequestCounter.getCount());
}
}Execution and Output:
D:\test>javac WebRequestCounterExample.java
D:\test>java WebRequestCounterExample
Total Requests: 2000Code language: CSS (css)
Program 5: Printer Resource Sharing
A single printer is shared by multiple employee threads. Object-level locking ensures that only one thread can use the printer at a time. Other threads must wait until the current printing task finishes. This prevents multiple documents from being printed simultaneously.
class Printer {
public void printDocument(String employee, String document) {
synchronized (this) {
System.out.println(employee + " started printing " + document);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(employee + " finished printing " + document);
}
}
}
class PrinterExample {
public static void main(String[] args) {
Printer printer = new Printer();
Thread t1 = new Thread(() ->
printer.printDocument("Ravi", "Report.pdf"));
Thread t2 = new Thread(() ->
printer.printDocument("Priya", "Invoice.pdf"));
t1.start();
t2.start();
}
}Execution and Output:
D:\test>javac PrinterExample.java
D:\test>java PrinterExample
Ravi started printing Report.pdf
Ravi finished printing Report.pdf
Priya started printing Invoice.pdf
Priya finished printing Invoice.pdfCode language: CSS (css)
Program 6: Online Shopping Cart
Multiple threads add and remove products from a shared shopping cart. ReentrantLock provides explicit locking for protecting the cart data. The lock ensures that only one modification occurs at a time. This keeps the cart quantity consistent.
import java.util.concurrent.locks.ReentrantLock;
class ShoppingCart {
private int items = 0;
private ReentrantLock lock = new ReentrantLock();
public void addItem(int quantity) {
lock.lock();
try {
items += quantity;
System.out.println("Added " + quantity +
" item(s). Cart: " + items);
} finally {
lock.unlock();
}
}
public void removeItem(int quantity) {
lock.lock();
try {
if (items >= quantity) {
items -= quantity;
System.out.println("Removed " + quantity +
" item(s). Cart: " + items);
} else {
System.out.println("Not enough items in cart.");
}
} finally {
lock.unlock();
}
}
}
class ShoppingCartExample {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
Thread t1 = new Thread(() -> cart.addItem(5));
Thread t2 = new Thread(() -> cart.removeItem(2));
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
}Execution and Output:
D:\test>javac ShoppingCartExample.java
D:\test>java ShoppingCartExample
Added 5 item(s). Cart: 5
Removed 2 item(s). Cart: 3Code language: CSS (css)
Program 7: ATM Cash Withdrawal
Multiple ATM threads access the same bank account simultaneously. The Lock interface is used to control access to the withdrawal operation. Only one ATM transaction can update the balance at a time. This prevents the account balance from becoming negative.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class ATMAccount {
private int balance = 8000;
private Lock lock = new ReentrantLock();
public void withdraw(String atm, int amount) {
lock.lock();
try {
if (balance >= amount) {
balance -= amount;
System.out.println(atm + " withdrew " + amount +
" | Balance: " + balance);
} else {
System.out.println(atm +
" transaction failed due to insufficient balance.");
}
} finally {
lock.unlock();
}
}
}
class ATMWithdrawalExample {
public static void main(String[] args) {
ATMAccount account = new ATMAccount();
Thread t1 = new Thread(() -> account.withdraw("ATM-1", 5000));
Thread t2 = new Thread(() -> account.withdraw("ATM-2", 4000));
t1.start();
t2.start();
}
}Execution and Output:
D:\test>javac ATMWithdrawalExample.java
D:\test>java ATMWithdrawalExample
ATM-1 withdrew 5000 | Balance: 3000
ATM-2 transaction failed due to insufficient balance.
Program 8: Restaurant Order Processing
Waiter threads add orders to a shared kitchen queue, while kitchen threads process the orders. The wait() method makes the consumer wait when no orders are available. The notify() method wakes up waiting threads when a new order arrives. This is a basic producer-consumer synchronization example.
import java.util.LinkedList;
import java.util.Queue;
class Kitchen {
private Queue<String> orders = new LinkedList<>();
public synchronized void addOrder(String order) {
orders.add(order);
System.out.println("Order received: " + order);
notify();
}
public synchronized void processOrder() {
while (orders.isEmpty()) {
try {
System.out.println("Kitchen waiting for orders...");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String order = orders.poll();
System.out.println("Kitchen processed: " + order);
}
}
class RestaurantExample {
public static void main(String[] args) {
Kitchen kitchen = new Kitchen();
Thread chef = new Thread(() -> kitchen.processOrder());
Thread waiter = new Thread(() -> kitchen.addOrder("Veg Biryani"));
chef.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
waiter.start();
}
}Execution and Output:
D:\test>javac RestaurantExample.java
D:\test>java RestaurantExample
Kitchen waiting for orders...
Order received: Veg Biryani
Kitchen processed: Veg BiryaniCode language: CSS (css)
Program 9: Student Marks Update System
Multiple faculty members may read and update a student’s marks. ReentrantReadWriteLock allows multiple threads to read simultaneously. However, only one thread can perform an update at a time. This improves safety and efficiency for systems with many readers.
import java.util.concurrent.locks.ReentrantReadWriteLock;
class StudentRecord {
private int marks = 80;
private ReentrantReadWriteLock lock =
new ReentrantReadWriteLock();
public void readMarks(String faculty) {
lock.readLock().lock();
try {
System.out.println(faculty +
" read marks: " + marks);
} finally {
lock.readLock().unlock();
}
}
public void updateMarks(String faculty, int newMarks) {
lock.writeLock().lock();
try {
marks = newMarks;
System.out.println(faculty +
" updated marks to: " + marks);
} finally {
lock.writeLock().unlock();
}
}
}
class StudentMarksExample {
public static void main(String[] args) {
StudentRecord student = new StudentRecord();
Thread t1 = new Thread(() ->
student.readMarks("Faculty-1"));
Thread t2 = new Thread(() ->
student.updateMarks("Faculty-2", 95));
Thread t3 = new Thread(() ->
student.readMarks("Faculty-3"));
t1.start();
t2.start();
t3.start();
}
}Execution and Output:
D:\test>javac StudentMarksExample.java
D:\test>java StudentMarksExample
Faculty-1 read marks: 80
Faculty-3 read marks: 80
Faculty-2 updated marks to: 95Code language: CSS (css)
Program 10: Darshan Ticket Reservation
A temple has a limited number of Darshan tickets available for devotees. A Semaphore controls access to the limited ticket resources. Each successful reservation acquires one permit. When no permits remain, additional devotees cannot reserve a ticket.
import java.util.concurrent.Semaphore;
class DarshanTickets {
private Semaphore tickets = new Semaphore(3);
public void reserveTicket(String devotee) {
if (tickets.tryAcquire()) {
System.out.println(devotee +
" reserved a Darshan ticket. Remaining: " +
tickets.availablePermits());
} else {
System.out.println(devotee +
" could not get a Darshan ticket.");
}
}
}
class DarshanTicketExample {
public static void main(String[] args) {
DarshanTickets reservation = new DarshanTickets();
Thread t1 = new Thread(() ->
reservation.reserveTicket("Devotee-1"));
Thread t2 = new Thread(() ->
reservation.reserveTicket("Devotee-2"));
Thread t3 = new Thread(() ->
reservation.reserveTicket("Devotee-3"));
Thread t4 = new Thread(() ->
reservation.reserveTicket("Devotee-4"));
t1.start();
t2.start();
t3.start();
t4.start();
}
}Execution and Output:
D:\test>javac DarshanTicketExample.java
D:\test>java DarshanTicketExample
Devotee-4 could not get a Darshan ticket.
Devotee-2 reserved a Darshan ticket. Remaining: 1
Devotee-3 reserved a Darshan ticket. Remaining: 0
Devotee-1 reserved a Darshan ticket. Remaining: 2Code language: JavaScript (javascript)
Program 11: Good Karma Counter
Multiple devotees perform good deeds at the same time, and each deed increases a shared counter. AtomicInteger provides thread-safe increment operations without using synchronized. The incrementAndGet() operation is atomic. Therefore, no updates are lost even when multiple threads increment simultaneously.
import java.util.concurrent.atomic.AtomicInteger;
class GoodKarmaCounter {
private AtomicInteger karma = new AtomicInteger(0);
public void performGoodDeed(String devotee) {
int points = karma.incrementAndGet();
System.out.println(devotee +
" performed a good deed. Karma Points: " + points);
}
public int getKarma() {
return karma.get();
}
}
class GoodKarmaExample {
public static void main(String[] args) throws InterruptedException {
GoodKarmaCounter counter = new GoodKarmaCounter();
Thread t1 = new Thread(() ->
counter.performGoodDeed("Devotee-1"));
Thread t2 = new Thread(() ->
counter.performGoodDeed("Devotee-2"));
Thread t3 = new Thread(() ->
counter.performGoodDeed("Devotee-3"));
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
System.out.println("Total Good Karma: " +
counter.getKarma());
}
}Execution and Output:
D:\test>javac GoodKarmaExample.java
D:\test>java GoodKarmaExample
Devotee-1 performed a good deed. Karma Points: 1
Devotee-2 performed a good deed. Karma Points: 2
Devotee-3 performed a good deed. Karma Points: 3
Total Good Karma: 3Code language: CSS (css)
Program 12: Philosophical Wisdom Sharing
Multiple students read shared philosophical teachings while another thread updates them. ReadWriteLock allows multiple readers to access the data simultaneously. A writer receives exclusive access while updating the collection. This provides safe and efficient synchronization for read-heavy applications.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
class WisdomCollection {
private List<String> teachings = new ArrayList<>();
private ReadWriteLock lock =
new ReentrantReadWriteLock();
public void readTeachings(String student) {
lock.readLock().lock();
try {
System.out.println(student +
" is reading: " + teachings);
} finally {
lock.readLock().unlock();
}
}
public void addTeaching(String teaching) {
lock.writeLock().lock();
try {
teachings.add(teaching);
System.out.println("New teaching added: " +
teaching);
} finally {
lock.writeLock().unlock();
}
}
}
class PhilosophicalWisdomExample {
public static void main(String[] args) {
WisdomCollection wisdom = new WisdomCollection();
wisdom.addTeaching("Practice kindness");
wisdom.addTeaching("Seek knowledge");
Thread t1 = new Thread(() ->
wisdom.readTeachings("Student-1"));
Thread t2 = new Thread(() ->
wisdom.readTeachings("Student-2"));
Thread t3 = new Thread(() ->
wisdom.addTeaching("Live with compassion"));
t1.start();
t2.start();
t3.start();
}
}Execution and Output:
D:\test>javac PhilosophicalWisdomExample.java
D:\test>java PhilosophicalWisdomExample
New teaching added: Practice kindness
New teaching added: Seek knowledge
Student-2 is reading: [Practice kindness, Seek knowledge]
Student-1 is reading: [Practice kindness, Seek knowledge]
New teaching added: Live with compassion
Code language: CSS (css)
