Безопасно ли получить доступ к этой переменной с помощью синхронизации? - PullRequest
0 голосов
/ 04 января 2012

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

Class SuperClassA {
     private Bitmap bmpA;

     protected abstract Bitmap createBitmap();

     public void run() {
          synchronized (this) {
               bmpA = createBitmap();
          }
     }

     // some other codes.
}

Class SubClassB extends SuperClassA {
     private Bitmap outBmpB;

     protected Bitmap createBitmap() {
          outBmpB = ..... // create and process "outBmpB".

          Bitmap bmp;
          bmp = ..... // create and process "bmp".
          return bmp;
     }

     public Bitmap getOutBmpB() {
          Bitmap tempBmp;
          synchronized (this) {
               tempBmp = outBmpB.clone();
          }
          return tempBmp;
     }

     // some other codes.
}

Метод getOutBmpB () в классе B выполняется потоком, а унаследованный метод run () в ClassB - другим потоком. Метод «createBitmap ()», реализованный в ClassB, должен запускаться в синхронизированном блоке внутри метода «run ()».

Мой вопрос заключается в том, что я не уверен, что эти две нити безопасно доступны для новой определенной переменной класса "outBmpB" в ClassB. Я не уверен, что блок «synchronized (this)» в методе «run ()» также «заблокирует» переменную «outBmpB», определенную только в ClassB? Если нет, то я мог бы добавить блок «synchronized (this)» в реализации «createBitmap ()». например,

 protected Bitmap createBitmap() {
      synchronized (this) {
           outBmpB = ..... // create and process "outBmpB".
      }

      Bitmap bmp;
      bmp = ..... // create and process "bmp".
      return bmp;
 }

Спасибо за любые предложения.

Lawrence

Ответы [ 3 ]

3 голосов
/ 04 января 2012

Вам не нужно синхронизировать , так как он уже синхронизирован в суперклассе и других вызовов нет, но вы должны это сделать. Ваша реализация createBitmap() основана на деталях реализации из суперкласса. Выполняйте синхронизацию в каждой точке доступа к общим полям.

В связи с этим ваш текущий код подкласса очень подвержен ошибкам!

Несмотря на то, что сомнительно когда-либо синхронизировать по this, гораздо лучше идея синхронизировать по частному объекту, к которому никто другой не может получить доступ. Таким образом, ваш код не может быть взломан клиентами, использующими ваши объекты класса, и синхронизироваться с ним.

1 голос
/ 04 января 2012

Речь не идет о блокировке переменной: вы просто не можете этого сделать.У вас есть правильная блокировка в вашем коде.Однако «безопасность потоков» означает «Это безопасно для любого разумного использования».Поскольку ваш метод, изменяющий outBmpB, равен protected, то есть доступен для членов пакета и всех дочерних элементов, лучше выполнять явную синхронизацию.

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

0 голосов
/ 04 января 2012

Как правило, лучше заблокировать объект, который вы используете (bmpA и outBmpB в вашем случае), чем объект-контейнер, если вам действительно не нужно это делать (и в этом случае синхронизироватьбудет лучше)* и поэтому гораздо лучше синхронизировать внутри createBitmap(), чем внутри run().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...