映画館のチケット販売システムを例に、スレッドセーフな処理の3つの方法を解説します。100席ある映画のチケット販売をシミュレートします。
- 基本的な実装と問題点 まずはスレッドセーフではない基本的な実装です:
public class TicketSales implements Runnable {
private int remainingSeats = 100;
public void run() {
while(true) {
if(remainingSeats > 0) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "が" + remainingSeats-- + "番目の席を販売");
}
}
}
}
public class MainApp {
public static void main(String[] args) {
TicketSales sales = new TicketSales();
new Thread(sales).start();
new Thread(sales).start();
new Thread(sales).start();
}
}
この実装では、重複販売や0枚目のチケットが表示される問題が発生します。
- 同期ブロックによる解決 synchronizedブロックを使用した解決方法:
public class SynchronizedTicketSales implements Runnable {
private int seats = 100;
private final Object lock = new Object();
public void run() {
while(true) {
synchronized(lock) {
if(seats > 0) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "が" + seats-- + "番目の席を確保");
}
}
}
}
}
- 同期メソッドによる解決 synchronizedメソッドを使用した方法:
public class MethodSyncTicketSales implements Runnable {
private int availableSeats = 100;
public void run() {
while(true) {
processSale();
}
}
private synchronized void processSale() {
if(availableSeats > 0) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "が" + availableSeats-- + "番目を予約");
}
}
}
- Lockインターフェースを使用した解決 ReentrantLockを使用したより柔軟な方法:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTicketSales implements Runnable {
private int totalSeats = 100;
private final Lock seatLock = new ReentrantLock();
public void run() {
while(true) {
seatLock.lock();
try {
if(totalSeats > 0) {
Thread.sleep(300);
System.out.println(Thread.currentThread().getName() + "が" + totalSeats-- + "番を購入");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
seatLock.unlock();
}
}
}
}
これらの方法はいずれも、チケットの重複販売や不正な値の問題を解決できます。