Подтвердить что ты не робот

Нужна ли дополнительная синхронизация при использовании BlockingQueue?

У меня есть простая bean @Entity Message.java, которая имеет некоторые нормальные свойства. Жизненный цикл этого объекта выглядит следующим образом

Активация сообщения происходит в потоке A, который затем помещается в blockingQueue

Другой поток из пула получает этот объект и выполняет некоторые вещи с ним и изменяет состояние сообщения, после чего объект снова входит в blockingQueue. Этот шаг повторяется до тех пор, пока условие не остановится. Каждый раз, когда объект получает чтение/запись, потенциально может быть из другого потока, но с гарантией, что он будет читать только один поток за раз.

Учитывая эти обстоятельства, мне нужно синхронизировать геттеры/сеттеры? Возможно, свойства нестабильны? или я могу просто уйти без синхронизации?

Спасибо и надеюсь, что смогу прояснить, что у меня здесь.

4b9b3361

Ответ 1

Нет, вам не нужно синхронизировать доступ к свойствам объекта или даже использовать volatile для переменных-членов.

Все действия, выполняемые потоком перед тем, как он ставит объект в очередь на BlockingQueue "произошел-до", объект будет удален. Это означает, что любые изменения, сделанные первым потоком, видны для второго. Это обычное поведение для одновременных коллекций. См. Последний абзац документация класса BlockingQueue.

Пока первый поток не производит никаких изменений после очередности объекта, он будет безопасным.

Ответ 2

Вам не нужно выполнять синхронизацию самостоятельно, потому что очередь делает это для вас уже.

Видимость также гарантируется.

Ответ 3

Если вы уверены, что только один поток за один раз получит доступ к вашему объекту, вам не потребуется синхронизация.

Однако вы можете убедиться, что с помощью синхронизированного ключевого слова: каждый раз, когда вы хотите получить доступ к этому объекту, и убедитесь, что ни один другой поток не использует один и тот же экземпляр, оберните код в синхронизированный блок:

Message myMessage = // ...
synchronized (myMessage) {
    // You're the only one to have access to this instance, do what you want
}

Синхронизированный блок получит неявный блокировку объекта myMessage. Таким образом, ни один другой синхронизированный блок не будет иметь доступ к тому же экземпляру, пока вы не покинете этот блок.

Ответ 4

Казалось бы, вы можете уйти от синхронных методов. Синхронизированный просто блокирует объект, чтобы разрешить доступ к нему только одному потоку. Вы уже обработали это с помощью блокирующей очереди.

Volatile будет полезен, так как это гарантирует, что каждый поток имеет самую последнюю версию вместо значения локального кэша потока.