Acho que me perdi no raciocínio abaixo, logo se alguém quiser comentar algo para me ajudar seria legal.
No exemplo da documentação da interface Condition da nova API de concorrência do Tiger, o seguinte exemplo é utilizado para demonstrar uma possível vantagem dessa abordagem:
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
Mas não seria impossível ter threads esperando em ambas as condições simultaneamente ??? Se o queue está cheio, ele não está vazio e se ele está vazio logo não está cheio. (duh!) Logo se tenho threads esperando numa condition (notFull) não terei threads esperando na outra condition (notEmpty) e vice-versa. Então pra que ter duas condições e não apenas uma ???
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition hadToWait = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
hadToWait.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
hadToWait.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
hadToWait.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
hadToWait.signal();
return x;
} finally {
lock.unlock();
}
}
}
Perguntas:
-
Estou certo em achar que o exemplo utilizado na documentação não é um bom exemplo onde mais de uma condição para um lock é necessário ?
-
Caso a resposta acima seja positiva, qual seria um exemplo realmente gritante onde duas condições para um único lock é essencial ?