Блок синхронизации внутри метода обратного вызова

Я использую Apache mina в одном из своих проектов. Функция doDecode() CumulativeProtocolDecoder вызывается каждый раз при получении порции данных. Я объединяю эти фрагменты вместе, пока не получу специальный символ в конце строки. Поэтому я начинаю конкатенацию, когда получаю $ в качестве первого символа, и заканчиваю конкатенацию, когда получаю еще один символ $.

Я хочу синхронизировать часть конкатенации, чтобы избежать любых потенциальных непреднамеренных конкатенаций.

Инкапсулируя блок конкатенации с помощью предложения synchronized(), я могу сделать эту операцию потокобезопасной, но Мой вопрос заключается в том, что пока один поток занят выполнением конкатенации, а другой поток вызывает doDecode() с новыми данными, будет ли новая информация предоставлена ​​как аргумент doDecode() будет потерян, потому что синхронизированный блок занят, или он будет ждать и хранить аргумент в кэше, пока синхронизированный блок снова не станет доступным?

@Override
    protected boolean doDecode(IoSession ioSession, IoBuffer ioBuffer, ProtocolDecoderOutput protocolDecoderOutput) throws Exception {
        System.out.println("inside decoder");

        try {
            IoBuffer data = (IoBuffer) ioBuffer;
            // create a byte array to hold the bytes
            byte[] buf = new byte[data.limit()];

            System.out.println("REPSONSE LENGTH: "+ data.limit());
            // pull the bytes out
            data.get(buf);
            // look at the message as a string
            String messageString = new String(buf);

            synchronized (messageString) {
                //do concatenatoin operatoins and other stuff
            }

        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

person user10286755    schedule 28.08.2018    source источник
comment
Вы каждый раз синхронизируете новый объект, что противоречит всей идее блокировок.   -  person Ivan    schedule 29.08.2018


Ответы (1)


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

Каждый поток, вызывающий doDecode, будет иметь собственную копию аргументов метода, так что вы можете быть уверены, что ни один аргумент не будет изменен между ними.

Я предполагаю, что объединение этих фрагментов означает сохранение их в некотором поле-члене вашего класса Decoder.

В этом случае вы, вероятно, захотите синхронизировать поле. Например:

private final Object lock = new Object();

@Override
protected boolean doDecode(IoSession ioSession, IoBuffer ioBuffer, ProtocolDecoderOutput protocolDecoderOutput) throws Exception {

    // ...
    synchronized (this.lock) {
        // do concatenation operations and other stuff
    }
    // ...
}

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

person Marko Pacak    schedule 28.08.2018