Nie. Twoja implementacja nie ma szansy zadzialac. Probowales to w ogole uruchomic zanim napisales posta?
- Twoj pseudokod wprowadza wiecej niejasnosci niz tlumaczy. Dla klarownosci uzywaj kodu Java.
- Czytelnik nie uzyskuje locka przed await() w metodzie wpuscCzytelnika(). Zgaduje ze skonczy sie to IllegalMonitorStateException
- Wprowadziles race condition na polach liczbaPisarzyBibioteka i liczbaCzytelnikowBiblioteka
- Wprowadziles race condition na polach WaitingReaders i WaitingWriters.
Nie wiem jak wyobrazasz sobie implementacje czegos co dziala jak ReadLock za pomoca Condition. Condition jest nierozerwalnie zwiazany z Lockiem, a lock implikuje mutual exclusion. Postaraj sie przeczytac ze zrozumieniem Javadoc dla Condition i Lock. Masz rowniez ewidentny problem ze zrozumieniem ze monitor nie jest substytutem locka, tylko jego fundamentalna czescia. Sa locki i semafory. Lock wpuszcza tylko jeden watek, a semafor okreslona ich ilosc. Do kontroli kolejki oczekujacych watkow potrzebny jest monitor. To wszystko.
Internet pelen jest przejrzystych, prostych, lepszych od mojego tlumaczen na temat tego czym jest lock. Wystarczy poszukac.
Ponizej implementacja i test
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Book {
public volatile long writes = 0L;
public volatile long reads = 0L;
public boolean moreThanOneWriter = false;
public boolean moreThanOneReader = false;
private final Lock lock = new ReentrantLock();
private final Condition canRead = lock.newCondition();
private final Condition canWrite = lock.newCondition();
private boolean ongoingWrite;
private int concurrentReaders;
public void write() {
lock.lock();
try {
while (concurrentReaders > 0 || ongoingWrite) canWrite.awaitUninterruptibly();
if (ongoingWrite) moreThanOneWriter = true;
ongoingWrite = true;
writes++;
} finally {
ongoingWrite = false;
canRead.signalAll();
lock.unlock();
}
}
public long read() {
lock.lock();
try {
while (ongoingWrite) canRead.awaitUninterruptibly();
if (++concurrentReaders > 1) moreThanOneReader = true;
reads++;
return writes;
} finally {
concurrentReaders--;
canWrite.signal();
lock.unlock();
}
}
}
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.LockSupport;
import static org.junit.Assert.*;
public class BookTest {
private static final int WRITERS = 3;
private static final int READERS = 5;
private static final long ITERATIONS = 5_000_000L;
@Test
public void bookTest() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(WRITERS + READERS);
final Book book = new Book();
for (int i = 0; i < WRITERS; i++) new Writer(book, ITERATIONS, latch).start();
for (int i = 0; i < READERS; i++) new Reader(book, ITERATIONS, latch).start();
new Thread() {
@Override
public void run() {
while (true) {
System.out.println("Writes: " + book.writes);
System.out.println("Reads: " + book.reads);
LockSupport.parkNanos(1_000_000_000L);
}
}
}.start();
latch.await();
assertEquals(WRITERS * ITERATIONS, book.writes);
assertEquals(READERS * ITERATIONS, book.reads);
assertFalse(book.moreThanOneWriter);
assertFalse(book.moreThanOneReader);
}
static class Writer extends Thread {
private final Book book;
private long writesLeft;
private final CountDownLatch latch;
Writer(final Book book, final long writes, final CountDownLatch latch) {
this.book = book; this.writesLeft = writes; this.latch = latch;
}
@Override
public void run() {
while (--writesLeft >= 0) book.write();
latch.countDown();
}
}
static class Reader extends Thread {
private final Book book;
private long readsLeft;
private final CountDownLatch latch;
Reader(final Book book, final long reads, final CountDownLatch latch) {
this.book = book; this.readsLeft = reads; this.latch = latch;
}
@Override
public void run() {
while (--readsLeft >= 0) book.read();
latch.countDown();
}
}
}
Powinno dzialac tak samo bez Condition.