У меня есть две функции, которые должны выполняться в критической секции:
public synchronized void f1() { ... }
public synchronized void f2() { ... }
Предположим, что поведение выглядит следующим образом:
f1
почти никогда не вызывается.На самом деле, в нормальных условиях этот метод никогда не вызывается.Если в любом случае вызывается f1
, он должен быстро вернуться. f2
вызывается с очень высокой скоростью.Он возвращается очень быстро. - Эти методы никогда не вызывают друг друга, и нет также и повторного входа.
Другими словами, очень низкий уровень разногласий.Поэтому, когда вызывается f2
, у нас есть некоторые накладные расходы для получения блокировки, которая предоставляется сразу в 99,9% случаев.Мне интересно, есть ли подходы, чтобы избежать этих издержек.
Я предложил следующую альтернативу:
private final AtomicInteger lock = new AtomicInteger(0);
public void f1() {
while (!lock.compareAndSet(0, 1)) {}
try {
...
} finally {
lock.set(0);
}
}
public void f2() {
while (!lock.compareAndSet(0, 2)) {}
try {
...
} finally {
lock.set(0);
}
}
Существуют ли другие подходы?Пакет java.util.concurrent
предлагает что-то изначально?
обновление
Хотя я собираюсь задать общий вопрос, некоторая информация о моей ситуации:
f1
: этот метод создает новый удаленный поток, если по какой-то причине текущий становится поврежденным, например, из-за тайм-аута.Удаленный поток может рассматриваться как соединение сокетов, которое использует удаленную очередь, начиная с заданного местоположения:
private Stream stream;
public synchronized void f1() {
final Stream stream = new Stream(...);
if (this.stream != null) {
stream.setPosition(this.stream.getPosition());
}
this.stream = stream;
return stream;
}
f2
: этот метод увеличивает позицию потока.Это простой установщик:
public synchronized void f2(Long p) {
stream.setPosition(p);
}
Здесь stream.setPosition(Long)
также реализован как простой установщик:
public class Stream {
private volatile Long position = 0;
public void setPosition(Long position) {
this.position = position;
}
}
В Stream
текущая позиция будет отправлена насервер периодически асинхронно.Обратите внимание, что Stream
не реализован мной самостоятельно.
Моя идея состояла в том, чтобы ввести сравнение и обмен, как показано выше, и пометить stream
как volatile
.