В настоящее время в нашей кодовой базе есть класс, который использует ключевое слово synchronized
на уровне метода для обеспечения согласованности данных в многопоточных операциях. Это выглядит примерно так:
public class Foo
{
public synchronized void abc() { ... }
public synchronized void def() { ... }
//etc.
}
Приятно то, что любой, кто использует класс, получает синхронизацию бесплатно. Когда вы создаете экземпляр Foo
, вам не нужно помнить о доступе к нему внутри блока synchronized
или чего-то подобного.
К сожалению, похоже, что синхронизация на уровне методов больше не поможет. Вместо этого нам придется начать синхронизацию на самом Foo
. Я не думаю, что что-то вроде java.util.concurrent.AtomicReference
тоже его сократит. Я хочу убедиться, что никто другой не коснется экземпляра Foo
, пока выполняется конкретная (и, возможно, довольно продолжительная) операция. Итак, теперь у нас в коде будут такие блоки:
Foo foo = new Foo(); //this got created somewhere
//somewhere else entirely
synchronized(foo)
{
//do operation on foo
foo.doStuff();
foo.doOtherStuff();
}
Итак, главное, что меня беспокоит, это то, что я и несколько разработчиков разделяем этот код. Объекты Foo
довольно распространены.Поскольку мы больше не получаем синхронизацию бесплатно на уровне метода, мы должны ВСЕГДА не забывать обращаться к объекту Foo
внутри блока synchronized
.
Итак, мой вопрос: есть ли в Java какой-либо механизм (встроенный или сторонний), позволяющий мне генерировать предупреждения или ошибки во время компиляции, если к экземпляру Foo
обращаются за пределами синхронизированный блок
?
В идеале это было бы что-то, что я мог бы сделать с объявлением класса (приведенный ниже пример):
@EnsureSynchronized
public class Foo
{
//etc.
}
Или что-то, что я мог бы сделать, объявляя экземпляры Foo
(составленный пример ниже):
@EnsureSynchronized
private Foo foo;
Я знаю, что если бы я действительно этого хотел, я, вероятно, мог бы написать собственное правило FindBugs или PMD для этого, но я надеялся, что что-то подобное уже существует.
Итак, я спрашиваю вас, сообщество SO, если бы вы оказались в такой ситуации, как бы вы попытались обеспечить доступ к объектам Foo
и их изменение только внутри синхронизированных
блоков?