Поток безопасный доступ к частному полю - PullRequest
0 голосов
/ 03 июля 2018

Итак, у меня есть следующий сценарий (не могу поделиться реальным кодом, но это будет что-то вроде этого):

public class Test
{
   private Object obj;

   public void init()
   {
       service.registerListener(new InnerTest());
   }

   public void readObj()
   {
       // read obj here
   }

   private class InnerTest implements Listener
   {
       public synchronized void updateObj()
       {
           Test.this.obj = new Object();
           // change the obj
       }
   }
}

Класс InnerTest зарегистрирован как слушатель в сервисе. Эта служба работает в одном потоке, вызовы readObj() производятся из другого потока, поэтому мой вопрос, чтобы обеспечить согласованность obj, достаточно ли для синхронизации метода UpdateObj()?

1 Ответ

0 голосов
/ 03 июля 2018

Я бы предложил использовать другой объект в качестве блокировки, чтобы гарантировать, что класс блокируется только при обращении к obj:

public class Test
{
   private final Object lock = new Object();
   private Object obj;

   public void init()
   {
       service.registerListener(new InnerTest());
   }

   public void readObj()
   {
       synchronized(lock){
           // read obj here
       }
   }

   private class InnerTest implements Listener
   {
       public void updateObj()
       {
           synchronized(Test.this.lock){
               Test.this.obj = new Object();
               // change the obj
           }
       }
   }
}

Затем используйте эту блокировку во всех методах, которым необходим постоянный доступ к obj. В вашем текущем примере методы readObj и updateObj.

Также, как указано в комментариях, использование synchronized на уровне метода в вашем классе InnerTest не будет работать так, как вы, вероятно, предполагали. Это потому, что синхронизированные методы будут использовать блок synchronized в переменной this. Который просто блокирует ваш InnerTest класс. Но не внешний Test класс.

...