Я создал образец для проверки:
public class RWLockTest {
public static final Logger LOGGER = LoggerFactory.getLogger(RWLockTest.class);
public static void main(String[] args) {
SomeClass someClass = new SomeClass();
Reader readerRunnable = new Reader(someClass);
Writer writerRunnable = new Writer(someClass);
//group 1 readers
for (int i = 0; i < 10; i++) {
new Thread(readerRunnable).start();
}
// 2 writers
new Thread(writerRunnable).start();
LOGGER.info("!!!!!!!!!!!!!!!WRITER_1 WAS STARTED!!!!!!!!!!!!!!!");
new Thread(writerRunnable).start();
LOGGER.info("!!!!!!!!!!!!!!!WRITER_2 WAS STARTED!!!!!!!!!!!!!!!");
//group 2 readers
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(readerRunnable);
LOGGER.info(String.format("%s was submitted", thread.getId()));
thread.start();
}
}
public static class SomeClass {
public ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public void read() {
readWriteLock.readLock().lock();
try {
LOGGER.info(String.format("Read by %s started", Thread.currentThread().getId()));
Thread.sleep(5000);
LOGGER.info(String.format("Read by %s finished", Thread.currentThread().getId()));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
public void write() {
readWriteLock.writeLock().lock();
try {
LOGGER.info(String.format("!!!!!!!!!!Write by %s started!!!!!!!!!!!!", Thread.currentThread().getId()));
Thread.sleep(3000);
LOGGER.info(String.format("!!!!!!!!!!Write by %s finished!!!!!!!!", Thread.currentThread().getId()));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
}
public static class Reader implements Runnable {
SomeClass someClass;
public Reader(SomeClass someClass) {
this.someClass = someClass;
}
@Override
public void run() {
someClass.read();
}
}
public static class Writer implements Runnable {
SomeClass someClass;
public Writer(SomeClass someClass) {
this.someClass = someClass;
}
@Override
public void run() {
someClass.write();
}
}
}
Я пытался запустить много времени, и вывод, как правило, выглядит так:
16:31:49.037 [main] INFO my.pack.RWLockTest - !!!!!!!!!!!!!!!WRITER_1 WAS STARTED!!!!!!!!!!!!!!!
16:31:49.040 [main] INFO my.pack.RWLockTest - !!!!!!!!!!!!!!!WRITER_2 WAS STARTED!!!!!!!!!!!!!!!
16:31:49.046 [Thread-1] INFO my.pack.RWLockTest - Read by 13 started
16:31:49.046 [main] INFO my.pack.RWLockTest - 24 was submitted
16:31:49.046 [Thread-7] INFO my.pack.RWLockTest - Read by 19 started
16:31:49.046 [Thread-4] INFO my.pack.RWLockTest - Read by 16 started
16:31:49.046 [Thread-5] INFO my.pack.RWLockTest - Read by 17 started
16:31:49.046 [Thread-0] INFO my.pack.RWLockTest - Read by 12 started
16:31:49.046 [Thread-3] INFO my.pack.RWLockTest - Read by 15 started
16:31:49.047 [main] INFO my.pack.RWLockTest - 25 was submitted
16:31:49.046 [Thread-9] INFO my.pack.RWLockTest - Read by 21 started
16:31:49.047 [Thread-8] INFO my.pack.RWLockTest - Read by 20 started
16:31:49.047 [main] INFO my.pack.RWLockTest - 26 was submitted
16:31:49.047 [Thread-2] INFO my.pack.RWLockTest - Read by 14 started
16:31:49.047 [Thread-6] INFO my.pack.RWLockTest - Read by 18 started
16:31:49.047 [main] INFO my.pack.RWLockTest - 27 was submitted
16:31:49.048 [main] INFO my.pack.RWLockTest - 28 was submitted
16:31:49.048 [main] INFO my.pack.RWLockTest - 29 was submitted
16:31:49.048 [main] INFO my.pack.RWLockTest - 30 was submitted
16:31:49.048 [main] INFO my.pack.RWLockTest - 31 was submitted
16:31:49.049 [main] INFO my.pack.RWLockTest - 32 was submitted
16:31:49.049 [main] INFO my.pack.RWLockTest - 33 was submitted
16:31:54.047 [Thread-7] INFO my.pack.RWLockTest - Read by 19 finished
16:31:54.048 [Thread-6] INFO my.pack.RWLockTest - Read by 18 finished
16:31:54.047 [Thread-5] INFO my.pack.RWLockTest - Read by 17 finished
16:31:54.049 [Thread-2] INFO my.pack.RWLockTest - Read by 14 finished
16:31:54.051 [Thread-8] INFO my.pack.RWLockTest - Read by 20 finished
16:31:54.047 [Thread-1] INFO my.pack.RWLockTest - Read by 13 finished
16:31:54.050 [Thread-9] INFO my.pack.RWLockTest - Read by 21 finished
16:31:54.049 [Thread-4] INFO my.pack.RWLockTest - Read by 16 finished
16:31:54.049 [Thread-3] INFO my.pack.RWLockTest - Read by 15 finished
16:31:54.049 [Thread-0] INFO my.pack.RWLockTest - Read by 12 finished
16:31:54.057 [Thread-10] INFO my.pack.RWLockTest - !!!!!!!!!!Write by 22 started!!!!!!!!!!!!
16:31:57.057 [Thread-10] INFO my.pack.RWLockTest - !!!!!!!!!!Write by 22 finished!!!!!!!!
16:31:57.058 [Thread-11] INFO my.pack.RWLockTest - !!!!!!!!!!Write by 23 started!!!!!!!!!!!!
16:32:00.060 [Thread-11] INFO my.pack.RWLockTest - !!!!!!!!!!Write by 23 finished!!!!!!!!
16:32:00.061 [Thread-13] INFO my.pack.RWLockTest - Read by 25 started
16:32:00.061 [Thread-14] INFO my.pack.RWLockTest - Read by 26 started
16:32:00.061 [Thread-12] INFO my.pack.RWLockTest - Read by 24 started
16:32:00.061 [Thread-15] INFO my.pack.RWLockTest - Read by 27 started
16:32:00.061 [Thread-17] INFO my.pack.RWLockTest - Read by 29 started
16:32:00.062 [Thread-19] INFO my.pack.RWLockTest - Read by 31 started
16:32:00.062 [Thread-18] INFO my.pack.RWLockTest - Read by 30 started
16:32:00.061 [Thread-16] INFO my.pack.RWLockTest - Read by 28 started
16:32:00.062 [Thread-20] INFO my.pack.RWLockTest - Read by 32 started
16:32:00.062 [Thread-21] INFO my.pack.RWLockTest - Read by 33 started
16:32:05.060 [Thread-12] INFO my.pack.RWLockTest - Read by 24 finished
16:32:05.060 [Thread-15] INFO my.pack.RWLockTest - Read by 27 finished
16:32:05.060 [Thread-13] INFO my.pack.RWLockTest - Read by 25 finished
16:32:05.060 [Thread-17] INFO my.pack.RWLockTest - Read by 29 finished
16:32:05.060 [Thread-14] INFO my.pack.RWLockTest - Read by 26 finished
16:32:05.062 [Thread-21] INFO my.pack.RWLockTest - Read by 33 finished
16:32:05.062 [Thread-16] INFO my.pack.RWLockTest - Read by 28 finished
16:32:05.062 [Thread-19] INFO my.pack.RWLockTest - Read by 31 finished
16:32:05.062 [Thread-18] INFO my.pack.RWLockTest - Read by 30 finished
16:32:05.062 [Thread-20] INFO my.pack.RWLockTest - Read by 32 finished
Что это делаетзначит?
Как видите, я делаю следующее:
- запустить 10 потоков для чтения. все 10 потоков могут работать параллельно. Каждое чтение занимает 5 секунд
- Затем я запускаю 2 писателя (1 запись занимает 3 секунды)
- Затем я запускаю 10 считывателей
Как вы видите задержку междупервая запись была отправлена (16:31:49.037 [main] INFO my.pack.RWLockTest - !!!!!!!!!!!!!!!WRITER_1 WAS STARTED!!!!!!!!!!!!!!!
), а когда она фактически указана ((полученная блокировка) 16:31:54.057 [Thread-10] INFO my.pack.RWLockTest - !!!!!!!!!!Write by 22 started!!!!!!!!!!!!
), составляет 5 секунд. Это время чтения.
Также вы можете видеть, что после того, как 2 потока писателей были отправлены, мы отправили 10 потоков читателей с идентификаторами от 24 до 33 , и все они были фактически запущены (полученыблокировок) после того, как авторский поток закончил свои работы.
Таким образом, потоки читателей с идентификаторами от 24 до 33 были представлены в 16:31:49
, и в это время readlock был получен первыми 10 читателями и выглядит какони также смогли получить блокировку чтения, но, похоже, внутри ReentrantReadWriteLock
есть что-то, что мешает избежать голодания писателя. В конце концов вторая группа читателей смогла получить блокировку только в 16:32:00
(через 6 секунд после отправки)
Я не знаю, гарантировано ли это, но из моих тестов это всегда работает таким образом. Таким образом, у нас есть некоторый приоритет Writers над Readers , хотя java doc говорит:
Этот класс не навязывает порядок чтения или записи для доступа к блокировке