package os;
import java.io.PrintStream;
import java.util.concurrent.Semaphore;
class Database {
Semaphore writeMut = new Semaphore(1);
Semaphore readSem = new Semaphore(1);
Semaphore mut = new Semaphore(1);
private int readersWorking = 0;
// Sva polja se inicijalizuju u konstruktoru
public Database() {
}
// Pocetak operacije citanja
public void readLock() {
mut.acquireUninterruptibly();
if(readersWorking==0)
{
writeMut.acquireUninterruptibly();
System.out.println("lock read");
}
readersWorking++;
mut.release();
}
// Pocetak operacije pisanja
public void writeLock() {
writeMut.acquireUninterruptibly();
}
// Kraj operacije citanja
public void readUnlock() {
mut.acquireUninterruptibly();
readersWorking--;
if(readersWorking==0)
{
writeMut.release();
System.out.println("unlock read");
}
mut.release();
}
// Kraj operacije pisanja
public void writeUnlock() {
writeMut.release();
}
}
public class ReadWriter {
// Broj proizvodjaca i potrosaca
public static final int READER_COUNT = 20;
public static final int WRITER_COUNT = 2;
// Potrebno vreme proizvodnje i potrosnje
public static final long READER_TIME = 2000;
public static final long WRITER_TIME = 500;
// Glavna nit
public static void main(String[] args) {
// Napravi bazu podataka kojoj ce procesi pristupati
Database database = new Database();
// Napravi citaoce
for (int i = 0; i < READER_COUNT; i++) {
Reader r = new Reader(database);
r.start();
}
// Napravi pisce
for (int i = 0; i < WRITER_COUNT; i++) {
Writer w = new Writer(database);
w.start();
}
}
// Sistem za ispisivanje poruka
public static int readersWorking = 0;
public static int readersWaiting = 0;
public static int writersWorking = 0;
public static int writersWaiting = 0;
public static void print() {
PrintStream out = (readersWorking * writersWorking != 0) ? System.err : System.out;
out.println("Readers: " + readersWorking + " (" + readersWaiting + ") Writers: " + writersWorking + " (" + writersWaiting + ")");
}
}
// Citalac
class Reader extends Thread {
private static int count = 1;
private Database database;
// Zapamti bazu i postavi ime procesa
public Reader(Database database) {
this.database = database;
setName("Reader " + count++);
}
@Override
public void run() {
while (!isInterrupted()) {
// Cekaj
try {
Thread.sleep((long)(ReadWriter.READER_TIME + Math.random() * ReadWriter.READER_TIME));
} catch (InterruptedException e) {
// Nema veze
}
// Pristupi bazi
synchronized (ReadWriter.class) { // Debug
ReadWriter.readersWaiting++;
ReadWriter.print();
}
database.readLock();
synchronized (ReadWriter.class) { // Debug
ReadWriter.readersWaiting--;
ReadWriter.readersWorking++;
ReadWriter.print();
}
// Citaj
try {
Thread.sleep((long)(ReadWriter.READER_TIME + Math.random() * ReadWriter.READER_TIME));
} catch (InterruptedException e) {
// Nema veze
}
// Oslobodi bazu
database.readUnlock();
synchronized (ReadWriter.class) { // Debug
ReadWriter.readersWorking--;
ReadWriter.print();
}
}
}
}
// Pisac
class Writer extends Thread {
private static int count = 1;
private Database database;
// Zapamti bazu i postavi ime procesa
public Writer(Database database) {
this.database = database;
setName("Writer " + count++);
}
@Override
public void run() {
while (!isInterrupted()) {
// Cekaj
try {
Thread.sleep((long)(ReadWriter.WRITER_TIME + Math.random() * ReadWriter.WRITER_TIME));
} catch (InterruptedException e) {
// Nema veze
}
// Pristupi bazi
synchronized (ReadWriter.class) { // Debug
ReadWriter.writersWaiting++;
ReadWriter.print();
}
database.writeLock();
synchronized (ReadWriter.class) { // Debug
ReadWriter.writersWaiting--;
ReadWriter.writersWorking++;
ReadWriter.print();
}
// Pisi
try {
Thread.sleep((long)(ReadWriter.WRITER_TIME + Math.random() * ReadWriter.WRITER_TIME));
} catch (InterruptedException e) {
// Nema veze
}
// Oslobodi bazu
database.writeUnlock();
synchronized (ReadWriter.class) { // Debug
ReadWriter.writersWorking--;
ReadWriter.print();
}
}
}
}