ReadWriteLock блокировка записи насыщена
У меня проблема с тем, что поток Writer голодает без блокировки. Пожалуйста, посмотрите на следующий код. Если я пытаюсь получить блокировку с помощью tryLock()
для блокировки чтения процесс записи станет голодным, и он никогда не сможет писать. Даже если честно, писательский процесс будет полностью истощен и никогда не будет выполнен. Вместо этого, если я попробую только reader.readLock()
тогда процесс записи сможет получить блокировку.
Пожалуйста, дайте мне знать, если я что-то упустил. Поток процесса записи, даже если он имеет высокий приоритет, никогда не захватывает блокировку и застревает в ожидании блокировки.
Может кто-нибудь, пожалуйста, скажите мне, могу ли я использовать trylock()
с ReadWriteLocks
,
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.*;
class ReadWrite{
private int a, j=0,k =0;
private final ReentrantReadWriteLock asd = new ReentrantReadWriteLock();
private final Lock readlock = asd.readLock();
private final Lock writelock = asd.writeLock();
ReadWrite(){
a = 0 ;
}
ReadWrite(int a){
this.a = a;
}
public int read() {
try {
if (readlock.tryLock())
{
//readlock.lock();
k = k + 1;
if (k%100000==0) {
System.out.println("read " + k + " times ==> Written " + j + " times");
}
readlock.unlock();
return a;
}
}
catch(Exception E) {
System.out.println(E);
return a;
}
return 0;
}
public void write(int a) {
int k = 9;
try {
writelock.lock();
//writelock.lock();
this.a = a;
k = 0;
j = j + 1;
System.out.println("Acquored");
}
catch(Exception E) {
System.out.println(E);
}
finally {
if (k == 0 )
writelock.unlock();
}
}
}
class reader implements Runnable{
ReadWrite a;
reader(Object b){
a = (ReadWrite) b;
}
public void run() {
while(true) {
try{a.read();
//Thread.sleep(100);
}
catch(Exception E) {
}
}
}
}
class writer implements Runnable{
ReadWrite a;
writer(Object b){
a = (ReadWrite) b;
}
public void run() {
//Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
while(true) {
try {
//Thread.sleep(1);
}
catch(Exception E) {
}
a.write((int) Math.ceil(Math.random()*100));
}
}
}
class Practice{
public static void main(String args[]) {
ReadWrite a = new ReadWrite();
System.out.println("Invoking Write Thread");
ExecutorService asd = Executors.newFixedThreadPool(100);
asd.execute(new writer(a));
for (int i = 0 ; i < 98 ; i ++)
asd.execute(new reader(a));
}
}
1 ответ
С использованием ReentrantReadWriteLock
в этом сценарии без справедливости, никогда не будет работать: слишком много потоков читателя будут просто голодать поток писателя.
Справедливости ради писательский поток получит случайный шанс написать.
Тем не менее, установка ReentrantReadWriteLock
Справедливость в вашем коде оказалась бесплодной. Вот жало: ваши читатели не используют lock()
, но tryLock()
, Таким образом, они никогда не ставятся в очередь для получения блокировки, они просто получают ее, если она доступна. И не в очереди (внутренне в ReentrantReadWriteLock
они обходят политику справедливости.
Обратите внимание на Javadoc на tryLock()
для ReadLock
объект:
Получает блокировку чтения, только если блокировка записи не удерживается другим потоком во время вызова. Получает блокировку чтения, если блокировка записи не удерживается другим потоком, и немедленно возвращает значение true. Даже если эта блокировка была настроена на использование политики справедливого упорядочения, вызов tryLock() немедленно получит блокировку чтения, если она доступна, независимо от того, ожидают ли другие потоки блокировки блокировки на чтение в данный момент. Такое "враждебное" поведение может быть полезным в определенных обстоятельствах, даже если оно нарушает справедливость. Если вы хотите выполнить настройку честности для этой блокировки, используйте tryLock(0, TimeUnit.SECONDS), который почти эквивалентен (он также обнаруживает прерывание).
Если блокировка записи удерживается другим потоком, тогда этот метод немедленно вернется со значением false.
(акцент мой)