Выполнение вызова метода с атомарными переменными Java

#java #multithreading #java.util.concurrent

#java #многопоточность #java.util.concurrent

Вопрос:

Предположим, у меня есть блок кода, подобный этому

 if (counter < 100) {
    synchronized (counter)
        if (counter < 100) {
            doSomething();
            counter.incrementAndGet();
        }
    }
}
  

где counter — это AtomicLong . Как бы мне преобразовать этот блок в то, чтобы больше не использовать synchronized ключевое слово и при этом сохранить его корректность? Или это невозможно?

Комментарии:

1. Предполагая, что counter является AtomicLong , ваш код не компилируется. Вы не можете сравнить объект и целое число, используя < оператор.

2. Что вы подразумеваете под «сохранением его корректности» — каким образом этот код корректен?

3. Поскольку у вас есть ‘doSomething’ внутри синхронизированного блока, AtomicLong на самом деле не является достаточной заменой. Вы могли бы использовать один из getAndUpdate , но это немного халтурно.

Ответ №1:

Все зависит от doSomething того, что вы не показали. Это может зависеть от вызова из синхронизированного блока и может даже не быть распараллеливаемым.

Одна замена, которая, я думаю, вероятно, будет приемлемой, это

 if (counter.getAndIncrement() < 100) {
    doSomething();
}
  

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

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

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

Комментарии:

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