Состояние сигнала без ожидающих потоков

1

Я использую 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();
}
  • 0
    Я не вижу, что вы производите или потребляете? Нужно больше кода. Я только что сделал такую проблему, и хитрость для потребителя состоит в том, чтобы сначала проверить доступность элемента (ов), а затем ждать, только если буфер пуст. Я не знаю, что вы на самом деле пытаетесь сделать, потому что здесь нет предметов для поиска.
  • 0
    У меня нет буфера в этом сценарии. У меня просто есть часть данных ( result ), которая устанавливается моим производителем, когда сообщение получено из сокета. Мне нужно, чтобы мой потребитель был уведомлен при получении сообщения. Моя проблема не в том, что потребитель ждет, несмотря на то, что буфер не пуст. Моя проблема в том, что, когда производитель устанавливает данные до того, как потребитель начал их ждать, потребитель в конечном итоге ждет, когда он в конечном итоге вызывает await() . Однако, когда производитель устанавливает данные (вызывает signal() ) после того, как потребитель вызвал await() все работает нормально.
Показать ещё 1 комментарий
Теги:
multithreading
race-condition
signals
reentrantlock

1 ответ

2
Лучший ответ

Это должно произойти, или я делаю что-то неправильно? Каково ожидаемое поведение, когда условие сигнализируется и нет ожидающих потоков?

Это должно произойти. Нет никакого эффекта, если нет нитей, ожидающих. В документе 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();
}
  • 0
    Отлично, спасибо! Моя вторичная проблема заключается в том, что result == null теста result == null самом деле не будет работать для меня, потому что у меня не будет возможности узнать, является ли результат "свежим" или он все еще висит раньше. Но это отдельная проблема, которую я могу решить, имея массив в качестве буфера вместо одной переменной. Еще раз спасибо.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню