import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ReadersWritersControl { private int readersCount = 0; private boolean isWriting = false; private final Lock lock = new ReentrantLock(); private final Condition canRead = lock.newCondition(); private final Condition canWrite = lock.newCondition(); public void startRead() throws InterruptedException { lock.lock(); try { while (isWriting) { canRead.await(); } readersCount++; } finally { lock.unlock(); } } public void endRead() { lock.lock(); try { readersCount--; if (readersCount == 0) { canWrite.signal(); } } finally { lock.unlock(); } } public void startWrite() throws InterruptedException { lock.lock(); try { while (isWriting || readersCount > 0) { canWrite.await(); } isWriting = true; } finally { lock.unlock(); } } public void endWrite() { lock.lock(); try { isWriting = false; canRead.signalAll(); canWrite.signal(); } finally { lock.unlock(); } } static class Reader implements Runnable { private final ReadersWritersControl control; Reader(ReadersWritersControl control) { this.control = control; } @Override public void run() { try { control.startRead(); System.out.println(Thread.currentThread().getName() + " is reading"); Thread.sleep(1000); // Simulating reading operation control.endRead(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } static class Writer implements Runnable { private final ReadersWritersControl control; Writer(ReadersWritersControl control) { this.control = control; } @Override public void run() { try { control.startWrite(); System.out.println(Thread.currentThread().getName() + " is writing"); Thread.sleep(1000); // Simulating writing operation control.endWrite(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } public static void main(String[] args) { ReadersWritersControl control = new ReadersWritersControl(); Thread reader1 = new Thread(new Reader(control), "Reader 1"); Thread reader2 = new Thread(new Reader(control), "Reader 2"); Thread writer1 = new Thread(new Writer(control), "Writer 1"); Thread writer2 = new Thread(new Writer(control), "Writer 2"); writer1.start(); reader1.start(); reader2.start(); writer2.start(); } }