Решение операций чтения/записи с использованием java-семафоров

Итак, это классическая проблема параллелизма, с которой мы (я и мой коллега) сталкиваемся здесь. Мы не поленились, Мы принесли соответствующий код, чтобы вы могли нам помочь должным образом. У нас есть два класса, определяющих Readers и Writers, они оба расширяют класс Thread и, конечно же, переопределяют метод run следующим образом:

while(!isInterrupted()) {
 try{ 
     Thread.sleep(for some time)
 }catch(InterruptedException e) {}

 database.readLock();
  readersWorking++; //for debugging purposes
 database.readUnlock();
}

Метод запуска в Writer почти такой же, но мы увеличиваем число WritersWorking также для целей отладки.

В нашем основном методе мы создаем 20 читателей и 2 писателей. Они оба получают один экземпляр класса базы данных через внедрение конструктора. Вот база данных:

class Database {
    Semaphore writeMut = new Semaphore(1);
    Semaphore readMut = new Semaphore(1);
    private int readersWorking = 0;

    public Database() {

    }

    public void readLock() {
        readMut.acquireUninterruptibly();

        if(readersWorking==0) //Am I the first one?
            writeMut.acquireUninterruptibly();
        readersWorking++;

        readMut.release();
    }

    public void writeLock() {
        writeMut.acquireUninterruptibly();
    }

    public void readUnlock() {
        readMut.acquireUninterruptibly();
        readersWorking--;
        if(readersWorking==0) //Am I the last one?
            writeMut.release();
        readMut.release();
    }

    public void writeUnlock() {
        writeMut.release();
    }
}

Вопрос: почему этот код приводит к тому, что наши читатели обращаются к базе данных, в то время как писатели все еще находятся в ней, и наоборот? Как мы можем отрицать, что это происходит? Что не так с нашей логикой здесь? Мы также ищем хорошую книгу по параллелизму в Java, если кто-нибудь знает такую.

На случай, если предоставленного кода недостаточно, вот полный код: http://codepad.org/IJ7e145C.


person nullpotent    schedule 14.11.2011    source источник
comment
Кажется, у вас есть несколько переменных ReaderWorking, WritersWorking в разных классах. Вы уверены, что это не сбивает с толку вашу статистику отладки?   -  person Tudor    schedule 14.11.2011


Ответы (2)


На самом деле я не в настроении тщательно анализировать ваш код (лень, я знаю :p), но похоже, что пакет java.util.concurrent.locks довольно много именно то, что вам нужно. Теперь, если вы не застряли с Java 1.4, я настоятельно рекомендую полагаться на утилиты параллелизма Java, которые сделают эту неприятную работу за вас. Вы облегчите себе задачу.

Что касается книги, похоже, что она подойдет.

person G_H    schedule 14.11.2011
comment
Большой +1. Используйте утилиты параллелизма Java и получите книгу Java Concurrency in Practice. - person user949300; 14.11.2011
comment
Ха... Эта ссылка с самого начала указывала на OutputStream? Это должен был быть ReadWriteLock, такой же, как опубликованный EJP. Извините за путаницу, я отредактировал. - person G_H; 15.11.2011