Я использую ReentrantLock
вместе с Condition
для синхронизации двух потоков. Всякий раз, когда потребительские потоки выполняют await()
при условии, что исполнительный поток выполняет signal()
, все работает нормально. Однако, когда поток производителя выполняет signal()
прежде чем потребительский поток выполнит ожидание await()
, потребительский поток просто заканчивается в ожидании. Это должно произойти, или я делаю что-то неправильно? Каково ожидаемое поведение, когда условие сигнализируется и нет ожидающих потоков?
Здесь код для потребителя:
this.lock.lock();
Log.d("websocket", "Sender acquired lock");
try
{
Log.d("websocket", "Sender waiting for message from server");
this.resultReady.await();
Log.d("websocket", "Sender waking up");
return this.result;
} catch (InterruptedException e)
{
e.printStackTrace();
}
finally {
this.lock.unlock();
}
Здесь код для производителя:
Log.d("websocket", "Receiver acquiring lock");
this.lock.lock();
Log.d("websocket", "Receiver acquired lock");
try
{
Log.d("websocket", "Receiver setting result");
result = serviceResult;
Log.d("websocket", "Receiver waking up waiting threads");
this.resultReady.signal();
} finally
{
this.lock.unlock();
}
Это должно произойти, или я делаю что-то неправильно? Каково ожидаемое поведение, когда условие сигнализируется и нет ожидающих потоков?
Это должно произойти. Нет никакого эффекта, если нет нитей, ожидающих. В документе Java говорится:
Пробуждает одну ожидающую нитку.
Если в этом состоянии ожидаются какие-либо потоки, то для пробуждения выбирается один. Затем этот поток должен повторно захватить замок, прежде чем вернуться с него.
Конечно, если нет нити, чтобы проснуться, значит, эффекта нет?
У вас есть буфер, содержащий один элемент, ваш result
. Вы должны проверить, что этот результат действителен независимо от метода await()
. Или переключитесь на нечто вроде Semaphore
которого есть внутреннее состояние, которое вы можете установить.
// Consumer
this.lock.lock();
Log.d("websocket", "Sender acquired lock");
try
{
Log.d("websocket", "Sender waiting for message from server");
while( result == null ) // CHANGE HERE
resultReady.await();
Log.d("websocket", "Sender waking up");
return this.result;
} catch (InterruptedException e)
{
e.printStackTrace();
}
finally {
this.lock.unlock();
}
result == null
теста result == null
самом деле не будет работать для меня, потому что у меня не будет возможности узнать, является ли результат "свежим" или он все еще висит раньше. Но это отдельная проблема, которую я могу решить, имея массив в качестве буфера вместо одной переменной. Еще раз спасибо.
result
), которая устанавливается моим производителем, когда сообщение получено из сокета. Мне нужно, чтобы мой потребитель был уведомлен при получении сообщения. Моя проблема не в том, что потребитель ждет, несмотря на то, что буфер не пуст. Моя проблема в том, что, когда производитель устанавливает данные до того, как потребитель начал их ждать, потребитель в конечном итоге ждет, когда он в конечном итоге вызываетawait()
. Однако, когда производитель устанавливает данные (вызываетsignal()
) после того, как потребитель вызвалawait()
все работает нормально.