在这里,我们用java构建了一个并发程序,在这个程序中,我们模拟了一个从中读取和写入的数据库。我们有20个同时阅读的读者和2个不同时阅读的作者。
读者开始阅读,写完之后,作家开始写作,这给作家造成了饥饿感。
我得到的结果是:
Reader 15 started reading
Reader 5 started reading
Reader 2 started reading
Reader 7 started reading
Reader 15 finished reading
Reader 5 finished reading
Reader 16 started reading
...
...
Writer 21 started writing
Writer 21 finished writing
Writer 20 started writing
Writer 20 finished writing
所以,我一直在尝试对这个程序执行fifo命令,以消除饥饿。例如,输出应该是r1、w1、r2、r3、r4、w2(r—reader,w—writer)。我被困在这一点上,我不知道是否改变我的算法与否。提前谢谢!
import java.util.concurrent.ThreadLocalRandom;
public class Runner {
public static void main(String[] args) {
try {
runDB(20, 2, new BetterDB());
} catch (InterruptedException ignored){}
}
static void runDB(int readersAmount, int writersAmount, DB database) throws InterruptedException {
assert readersAmount > 0;
assert writersAmount > 0;
Thread[] threads = new Thread[readersAmount + writersAmount];
for (int i = 0; i < readersAmount; i++){
threads[i] = new Thread(new Reader(database, i));
}
for (int i = readersAmount; i < readersAmount + writersAmount; i++){
threads[i] = new Thread(new Writer(database, i));
}
for (Thread thread : threads){
thread.start();
}
for (Thread thread : threads){
thread.join();
}
}
}
interface DB {
void read(int readerID) throws InterruptedException;
void write(int writerId);
}
class BetterDB implements DB {
long READ_TIME = 500; // milliseconds
long WRITE_TIME = 1000; // milliseconds
int readers = 0;
@Override
public void read(int readerID) throws InterruptedException {
synchronized (this) {
readers++;
System.out.printf("Reader %d started reading\n", readerID);
}
try {
ThreadLocalRandom random = ThreadLocalRandom.current();
Thread.sleep(random.nextLong(READ_TIME));
} catch (InterruptedException ignored) {}
synchronized (this) {
readers--;
System.out.printf("Reader %d finished reading\n", readerID);
if (readers == 0) {
this.notifyAll();
}
}
}
@Override
public synchronized void write(int writerId) {
try{
while(readers > 0){
this.wait();
}
} catch (InterruptedException ignored) {}
System.out.printf("Writer %d started writing\n", writerId);
try{
ThreadLocalRandom random = ThreadLocalRandom.current();
Thread.sleep(random.nextLong(WRITE_TIME));
} catch (InterruptedException ignored) {}
System.out.printf("Writer %d finished writing\n", writerId);
}
}
class Reader implements Runnable {
final long READER_DELAY = 500; // milliseconds
private final DB database;
private int id;
Reader(DB database, int id){
this.database = database;
this.id = id;
}
@Override
public void run() {
try{
ThreadLocalRandom random = ThreadLocalRandom.current();
Thread.sleep(random.nextLong(READER_DELAY));
database.read(id);
} catch (InterruptedException ignored) {}
}
}
class Writer implements Runnable {
final long WRITER_DELAY = 400; // milliseconds
private final DB database;
private int id;
Writer(DB database, int id){
this.database = database;
this.id = id;
}
@Override
public void run() {
try{
ThreadLocalRandom random = ThreadLocalRandom.current();
Thread.sleep(random.nextLong(WRITER_DELAY));
database.write(id);
} catch (InterruptedException ignored) {}
}
}
1条答案
按热度按时间e5njpo681#
如果我理解你的意图,你希望你的作者能够暂停读者,让他们有机会写作?
现在,他们被淹没了。所有的读者都可以保持忙碌,因为有20个,他们都可以同时运行,而且他们都会暂停足够长的时间,以使一个作家能够获得同步锁的可能性非常低。
听起来您需要实现更复杂的锁定,例如“request two write”锁定。你可以让你的编剧增加锁,然后在完成后减少它。读卡器需要类似的逻辑,写卡器需要检查是否有写锁请求。